Sed\AWK

Sed

sed 命令的基本语法如下:

sed [option] [address] command filename

sed 当中几个常用的命令:

  • s 替换
  • d 删除
  • a 追加
  • i 插入
  • c 修改

替换

sed [option] [address] s/pattern/replacement/flags

简单的例子如下:

$ cat a.txt
that is my
hasd is asd
$ sed "s/is/my/" a.txt
that my my
hasd my asd

pattern 代表的是正则表达式

$ sed "s/^/#/" sed2 
#that is my
#hasd is asd

replacement 是一个字符串,用来替换与正则表达式匹配的内容。在 replacement 部分,只有下列字符有特殊含义:

  • & 正则表达式匹配的内容
  • \n 匹配第 n 个字符串(n 是数字)
  • \ 转义 & 和 \
$ sed "s/is/[&]/" sed2 
that [is] my
hasd [is] asd
$ cat sed
This is my cat, my cat's name is betty

$ sed "s/This is my \([^,]*\),.*is \(.*\)/\1:\2/g" sed  
cat:betty

flags 是修饰替换的标志,有如下几种情况:

  • n 1~512 之间的整数,表示替换几次
  • g 表示全部替换
  • p 打印替换后的内容

删除

$ cat sed2 
that is my
hasd thy asd
$ sed "/is/d" a.txt
hasd thy asd

address

sed 命令可以指定 0-2 个地址,会有如下的规则:

  • 如果没匹配地址,那么命令会应用于每一行。
  • 如果只有一个地址,那么命令应用于与这个地址匹配的任意行。
  • 如果指定了由逗号分割的两个地址,那么命令应用于匹配第一个地址的第一行和它后面的行,一直到匹配第二个地址的行(包括此行)。
  • 如果地址后面带 ! ,那么命令就应该用于不匹配该地址的所有行。
$ cat sed2 
that is my
hasd is asd
rcx is tc
wwda srgad sd
wfecvvd se2d 

$ sed "/asd/,/rcx/! d" sed2
hasd is asd
rcx is tc

sed "/asd/! d" sed2      
hasd is asd

address 支持的类型如下:

  • n,数字类型代表第 n 行
  • first~step,从第 first 行开始,匹配步长为 step 的行
  • $,最后一行
  • /regexp/,正则表达式
  • addr1,+N,匹配 addr1 和后面的 N 行
  • addr1,~N,匹配 addr1 一直到行号是 N 的倍数的行
$ cat sed2 
that is my
hasd is asd
rcx is tc
wwda srgad sd
wfecvvd se2d

$ sed "1d" sed2       
hasd is asd
rcx is tc
wwda srgad sd
wfecvvd se2d

$ sed "1~2d" sed2 
hasd is asd
wwda srgad sd

$ sed "$ d" sed2 
that is my
hasd is asd
rcx is tc
wwda srgad sd

sed "1,+2 d" sed2     
wwda srgad sd
wfecvvd se2d 

$ sed "1,~4 d" sed2  
wfecvvd se2d 

追加、插入和更改

$ cat sed2 
that is my
hasd is asd
rcx is tc
wwda srgad sd
wfecvvd se2d

sed "/is/i new line" sed2 
new line
that is my
new line
hasd is asd
new line
rcx is tc
wwda srgad sd
wfecvvd se2d

$ sed "2 a new line" sed2
that is my
hasd is asd
new line
rcx is tc
wwda srgad sd
wfecvvd se2d 

$ sed "2 c new line" sed2 
that is my
new line
rcx is tc
wwda srgad sd
wfecvvd se2d 

多行匹配

$ cat pets.txt
This is my cat
  my cat's name is betty
This is my dog
  my dog's name is frank
This is my fish
  my fish's name is george
This is my goat
  my goat's name is adam

$ sed '1,3s/my/your/g; 3,$s/This/That/g' my.txt
This is your cat, your cat's name is betty
This is your dog, your dog's name is frank
That is your fish, your fish's name is george
That is my goat, my goat's name is adam

$ sed -e '1,3s/my/your/g' -e '3,$s/This/That/g' my.txt

分组命令

sed 中使用大括号 {} 将一个地址嵌套在另外一个地址中,或者在相同地址上使用多个命令,看如下例子:

$ cat ca
.a asdad 4tert

asd line
.b sdd line
sd s line
$ sed '/^\.a/,/^\.b/{/^$/d;s/line/Line/}' ca
.a asdad 4tert
asd Line
.b sdd Line
sd s line

Awk

如下一个简单的 awk 示例:

$ cat a.txt
Proto Recv-Q Send-Q Local-Address          Foreign-Address             State
tcp        0      0 0.0.0.0:3306           0.0.0.0:*                   LISTEN
tcp        0      0 0.0.0.0:80             0.0.0.0:*                   LISTEN
tcp        0      0 127.0.0.1:9000         0.0.0.0:*                   LISTEN
$ awk '{ print "hello world"}' a.txt
hello world
hello world
hello world
hello world

其中单引号中的被大括号括着的就是 awk 的语句,只能被单引号包含。

awk 允许你编写两个特殊的例程,分别是与 BEGIN 和 END 相关的过程。并且它们两个是可选的。

可以把 awk 看成三个部分组成:处理输入前将做的处理,处理输入过程中做的处理,处理输入完成后做的处理。

$ awk 'BEGIN {print "begin"} {print $0} END {print "END"}' a.txt
begin
Proto Recv-Q Send-Q Local-Address          Foreign-Address             State
tcp        0      0 0.0.0.0:3306           0.0.0.0:*                   LISTEN
tcp        0      0 0.0.0.0:80             0.0.0.0:*                   LISTEN
tcp        0      0 127.0.0.1:9000         0.0.0.0:*                   LISTEN
END

字段

awk 允许使用字段操作符 $ 来指定字段。$1 表示第一个字段,以此类推。$0 表示整行输入记录。

$ awk '{print $1}' awk 
Proto
tcp
tcp
tcp

分隔符

可以使用 -F 选项来改变字段分隔符。

$ echo "a##b##c" | awk -F## '{print $1}' 
a
$ echo "a##b##c" | awk -F "##" '{print $1}' 
a

字段的划分:

  • 设置成一个空格,这种情况记录的前导空白字符和结尾空白字符会被忽略,并且字段用空格或制表来分隔,FS 默认的就是一个空格。
  • 设置成一个单个字符,在这个字符出现的任何地方都将分隔出另外一个字段,如果两个连续的分隔符,在它们之间的字段值为空串。
  • 设置成多个字符,它将被作为一个正则表达式来解释。
$ echo "a##b" | awk -F# '{print $1 "-"  $2 "-" $3}'
a--b

$ echo "a#b##c###d####e" | awk -F "#+" '{print $1,$2,$3,$4,$5}'      
a b c d e

内置变量

变量解释
$0当前记录(这个变量中存放着整个行的内容)
1 1~1 n当前记录的第n个字段,字段间由FS分隔
FS输入字段分隔符 默认是空格或Tab
NF当前记录中的字段个数,就是有多少列
NR已经读出的记录数,就是行号,从1开始,如果有多个文件话,这个值也是不断累加中。
FNR当前记录数,与NR不同的是,这个值会是各个文件自己的行号
RS输入的记录分隔符, 默认为换行符
OFS输出字段分隔符, 默认也是空格
ORS输出的记录分隔符,默认为换行符
FILENAME当前输入文件的名字
$ echo "a#b#c#d#e" | awk  'BEGIN {FS="#"} {print $1,$2,$3,$4,$5}'      
a b c d e
$ echo "a#b#c#d#e" | awk  'BEGIN {FS = "#";OFS = ","} {print $1,$2,$3,$4,$5}' 
a,b,c,d,e

模式匹配

在 awk 读入一行时,它试图匹配脚本中的每一个模式匹配规则。只有与一个特定的模式相匹配的输入行才能成为操作对象。

$ cat awk 
Proto Recv-Q Send-Q Local-Address          Foreign-Address             State
tcp        0      0 0.0.0.0:3306           0.0.0.0:*                   LISTEN
tcp        0      0 0.0.0.0:80             0.0.0.0:*                   LISTEN
tcp        0      0 127.0.0.1:9000         0.0.0.0:*                   LISTEN
$ awk '/LISTEN/ {print $0}' awk 
tcp        0      0 0.0.0.0:3306           0.0.0.0:*                   LISTEN
tcp        0      0 0.0.0.0:80             0.0.0.0:*                   LISTEN
tcp        0      0 127.0.0.1:9000         0.0.0.0:*                   LISTEN

我们也可以测试匹配指定的字段,使用 ~ 操作符可以测试一个字段的正则匹配。

$ awk '$6 ~ /LISTEN/ {print $0}' awk 
tcp        0      0 0.0.0.0:3306           0.0.0.0:*                   LISTEN
tcp        0      0 0.0.0.0:80             0.0.0.0:*                   LISTEN
tcp        0      0 127.0.0.1:9000         0.0.0.0:*                   LISTEN

关系操作符

操作符描述
<小于
>大于
<=小于或等于
>=大于或等于
==相等
!=不相等
~匹配
!~不匹配

关系表达式可以用在模式中来控制特殊的操作。

$ cat awk1
name age
rcx  19
rcx1 29
rcx2 27
$ awk '$2==29 {print $1,$2}' awk1
rcx1 29

布尔操作符如下表:

操作符定义
||逻辑或
&&逻辑与
!逻辑非
$ awk '$2==29 || NR==1 {print $1,$2}' awk1 
name age
rcx1 29

条件语句

if ( expression ) {
     action
 }
else if (expression2) {
     action1
}
else {
     action2
}
$ cat awk1
name age
rcx  19
rcx1 29
rcx2 27
$ awk '{if(NR==2) print $0}' awk1
rcx  19

循环

while (condition) {
     action
}
do {
     action
} while (condition)
for (set_counter; test_counter; increment_counter) {
     action
}
for (i = 1; i <= 5; i++) {
     print i
}
$ cat score.txt
Marry   2143 78 84 77
Jack    2321 66 78 45
Tom     2122 48 77 71
Mike    2537 87 97 95
Bob     2415 40 57 62
$ awk '{sum+=$2} END {print sum}' score.txt
11538

数组

可以用数组存储一组变量,在 awk 当中不必指明数组的大小。数组的下标可以是字符或数字。

array[name] = "rcx"
array[1] = "chx"

循环访问数组

for(var in array) {
    do action with array[var]
}

系统变量数组

awk 中提供的两个系统变量 ARGV 和 ENVIRON 是数组。

ARGV 是一个命令行参数的数组,不包括脚本本身和任何调用 awk 指定的选项,这个数组元素的个数可以从 ARGC 获得。数组第一个元素的下标是 0。

ENVIRON 是一个环境变量数组,数组中每一个元素是当前环境变量的值,下标是环境变量的名字。

$ awk 'BEGIN {for(x=0;x<ARGC;x++) {print ARGV[x]} }' sro 
awk
sro

$ a=123
$ export a
$ awk 'END {print ENVIRON["a"]}' a.txt
123
<think>好的,用户想了解sedawk之间的区别及使用场景。首先,我需要回忆一下这两个工具的基本功能和他们各自的特点。根据之前提供的引用资料,比如引用[3]提到grep擅长查找,sed擅长修改,而awk擅长数据切片和格式化,这应该是一个好的切入点。 首先,我应该明确sedawk的不同设计目标。sed主要是流编辑器,用于对文本进行逐行处理,执行替换、删除、插入等操作。而awk更偏向于编程语言,能够处理结构化的文本数据,比如按列处理。用户可能需要具体的例子来理解两者的差异,比如替换文本中的字符串,用sed可能更直接,而处理表格数据用awk更方便。 然后,我需要考虑用户可能的实际使用场景。例如,用户可能需要进行批量文本替换,这时候sed更合适;或者需要处理日志文件,提取特定列的数据,这时候awk会更高效。引用[4]中提到的提取文件指定行之间的代码的例子,结合了awksed,说明两者可以互补使用。 接下来,用户可能想知道性能方面的差异,但根据已有的资料,没有直接提到性能比较,可能需要避免猜测。不过可以提到sed在处理简单替换时更高效,而awk在处理复杂数据时更灵活。 另外,语法结构的不同也很重要。引用[2]中提到了awk的结构,包括BEGIN和END块,而sed通常是一行命令。这可以作为两者的另一个区别点。 还要注意用户可能混淆两者的功能,比如用awk做替换或用sed处理列数据,这时候需要指出各自的强项。例如,虽然sed可以处理行内的模式,但awk的字段分割功能更适合列处理。 最后,总结两者的主要区别,强调sed适合行级文本编辑,而awk适合结构化数据处理,并给出典型的使用场景,帮助用户根据需求选择合适的工具。同时,可能需要生成相关问题,比如如何选择工具,或者两者结合使用的例子,但根据用户的问题,可能只需要专注于区别和场景。</think>### sedawk的区别及使用场景分析 --- #### **核心区别对比表** | 特性 | sed (流编辑器) | awk (文本分析器) | |-----------|--------------|----------------| | 设计定位 | 文本流编辑 | 结构化数据处理 | | 处理单位 | 按行处理 | 按列/字段处理 | | 编程能力 | 简单命令模式 | 完整编程语言支持 | | 典型场景 | 替换/删除/插入 | 数据提取/格式转换/统计 | | 正则表达式复杂度 | 基础正则语法 | 支持扩展正则表达式 | | 字段处理能力 | 弱(需手动分割) | 强(自动字段分割) | --- #### **详细区别说明** 1. **设计目标差异** - **sed**:专注于*流式文本编辑*,设计用于执行`过滤-处理-输出`的线性工作流。例如批量替换文本中的字符串: ```bash sed 's/old/new/g' file.txt # 全局替换old为new[^3] ``` - **awk**:构建为*数据报表生成工具*,支持`字段分割+条件判断+数学运算`。例如计算CSV文件第二列总和: ```bash awk -F',' '{sum+=$2} END{print sum}' data.csv ``` 2. **数据处理维度** - **sed** 以*行*为处理单位,适合处理连续文本流。如删除空行: ```bash sed '/^$/d' input.log ``` - **awk** 以*字段*为处理单位,默认按空格/TAB分割列。如提取进程CPU占用: ```bash ps aux | awk '{print $3,$11}' # 显示CPU%和命令名[^5] ``` 3. **编程能力对比** - **sed** 使用受限的`命令模式`,支持基础逻辑操作: ```bash sed '/error/p; /debug/d' app.log # 打印含error的行,删除含debug的行 ``` - **awk** 提供完整的编程结构(变量/数组/函数),如统计不同状态码出现次数: ```bash awk '{status[$9]++} END{for(s in status) print s,status[s]}' access.log ``` --- #### **典型使用场景** 1. **优先使用sed的情况** - ✅ 批量替换文件内容(如版本号更新) - ✅ 删除/保留特定模式的行 - ✅ 简单文本格式调整(如行号添加) *示例*:转换Windows换行符为Unix格式 ```bash sed -i 's/\r$//' script.sh ``` 2. **优先使用awk的情况** - ✅ 表格数据提取(如日志分析) - ✅ 数据统计计算(如求平均值/总和) - ✅ 复杂格式转换(如CSV转Markdown表格) *示例*:生成Apache日志状态码分布报告 ```bash awk '{print $9}' access.log | sort | uniq -c | awk '{print "状态码",$2,"出现次数",$1}' ``` --- #### **协同工作模式** 两者常通过管道组合使用,例如提取Nginx日志中响应时间大于1秒的请求: ```bash awk '$NF > 1 {print $7}' access.log | sed 's/\?.*//' | sort | uniq -c ``` ▸ `awk`筛选慢请求并提取URL路径 ▸ `sed`去除URL参数 ▸ 最终统计高频慢接口[^4] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值