语法格式
sed [-nefir] ‘command‘ file(s)
sed [-nefir] -f scriptfile file(s)
常用选项:
-n∶使用安静(silent)模式。在一般 sed 的用法中,sed在所有的脚本指令执行完毕后,将自动打印模式空间中的内容到屏幕上。但如果加上 -n 参数后,则只有经过sed 特殊处理的那一行(或者动作)才会被列出来。
-e∶直接在指令列模式上进行 sed 的动作编辑;
-f∶直接将 sed 的动作写在一个档案内, -f filename 则可以执行 filename 内的sed 动作;
-r∶sed 的动作支援的是延伸型正规表示法的语法。(预设是基础正规表示法语法)
-i∶直接修改读取的档案内容,而不是由萤幕输出。
常用指令:
名称 | 命令 | 语法 | 说明 |
---|---|---|---|
替换 | s | [address]s/pattern/replacement/flags | 替换匹配的内容 |
删除 | d | [address]d | 删除匹配的行 |
插入 | i | [line-address]i\
text |
在匹配行的前方插入文本 |
追加 | a | [line-address]a\
text |
在匹配行的后方插入文本 |
行替换 | c | [address]c\
text |
将匹配的行替换成文本text |
打印行 | p | [address]p | 打印在模式空间中的行 |
打印行号 | = | [address]= | 打印当前行行号 |
打印行 | l | [address]l | 打印在模式空间中的行,同时显示控制字符 |
转换字符 | y | [address]y/SET1/SET2/ | 将SET1中出现的字符替换成SET2中对应位置的字符 |
读取下一行 | n | [address]n | 将下一行的内容读取到模式空间 |
读文件 | r | [line-address]r file | 将指定的文件读取到匹配行之后 |
写文件 | w | [address]w file | 将匹配地址的所有行输出到指定的文件中 |
退出 | q | [line-address]q | 读取到匹配的行之后即退出 |
待需要处理的文本test.txt内容如下:
DEVICE=eth1 HWADDR=00:0c:29:c5:ae:ed TYPE=Ethernet UUID=bb4e221b-6953-4bfd-9842-fd442c02ae8e ONBOOT=yes NM_CONTROLLED=yes BOOTPROTO=dhcp DNS1=202.96.18.166 IPV6INIT=no USERCTL=no PEERDNS=yes
sed选项
a 追加:
例子
在第三行后面增加一行,内容为ipv4=192.168.1.1
sed ‘3a ipv4=192.168.1.1‘ test.txt
结果
DEVICE=eth1 HWADDR=00:0c:29:c5:ae:ed TYPE=Ethernet ipv4=192.168.1.1 UUID=bb4e221b-6953-4bfd-9842-fd442c02ae8e ONBOOT=yes NM_CONTROLLED=yes BOOTPROTO=dhcp DNS1=202.96.18.166 IPV6INIT=no USERCTL=no PEERDNS=yes
i 插入:
例子
在第三行前面增加一行,内容为ipv4=192.168.1.1
sed ‘3i ipv4=192.168.1.1‘ test.txt
结果
DEVICE=eth1 HWADDR=00:0c:29:c5:ae:ed ipv4=192.168.1.1 TYPE=Ethernet UUID=bb4e221b-6953-4bfd-9842-fd442c02ae8e ONBOOT=yes NM_CONTROLLED=yes BOOTPROTO=dhcp DNS1=202.96.18.166 IPV6INIT=no USERCTL=no PEERDNS=yes
s 替换:
例子
将所有的yes改为NO
sed ‘s/yes/NO/g‘ test.txt
结果
DEVICE=eth1 HWADDR=00:0c:29:c5:ae:ed TYPE=Ethernet UUID=bb4e221b-6953-4bfd-9842-fd442c02ae8e ONBOOT=NO NM_CONTROLLED=NO BOOTPROTO=dhcp DNS1=202.96.18.166 IPV6INIT=no USERCTL=no PEERDNS=NO
例子
在每行行首加上#
sed ‘s/^/#&/g‘ test.txt
结果
#DEVICE=eth1 #HWADDR=00:0c:29:c5:ae:ed #TYPE=Ethernet #UUID=bb4e221b-6953-4bfd-9842-fd442c02ae8e #ONBOOT=yes #NM_CONTROLLED=yes #BOOTPROTO=dhcp #DNS1=202.96.18.166 #IPV6INIT=no #USERCTL=no #PEERDNS=yes
在每行行尾加上#
sed ‘s/$/&#/g‘ test.txt
结果
DEVICE=eth1# HWADDR=00:0c:29:c5:ae:ed# TYPE=Ethernet# UUID=bb4e221b-6953-4bfd-9842-fd442c02ae8e# ONBOOT=yes# NM_CONTROLLED=yes# BOOTPROTO=dhcp# DNS1=202.96.18.166# IPV6INIT=no# USERCTL=no# PEERDNS=yes#
除了第三行外,所有行的末尾加上#
[[email protected] ~]# sed ‘3! s/$/&#/g‘ test.txt DEVICE=eth1# HWADDR=00:0c:29:c5:ae:ed# TYPE=Ethernet UUID=bb4e221b-6953-4bfd-9842-fd442c02ae8e# ONBOOT=yes# NM_CONTROLLED=yes# BOOTPROTO=dhcp# DNS1=202.96.18.166# IPV6INIT=no# USERCTL=no# PEERDNS=yes#
排除IPV6所在的行,其他行行尾加上#
[[email protected] ~]# sed ‘/IPV6/!s/$/&#/g‘ test.txt DEVICE=eth1# HWADDR=00:0c:29:c5:ae:ed# TYPE=Ethernet# UUID=bb4e221b-6953-4bfd-9842-fd442c02ae8e# ONBOOT=yes# NM_CONTROLLED=yes# BOOTPROTO=dhcp# DNS1=202.96.18.166# IPV6INIT=no USERCTL=no# PEERDNS=yes#
高级应用
p和P
p:打印当前模式空间内容,追加到默认输出之后;
P:打印当前模式空间开端至\n的内容,并追加到默认输出之前;
n和N
n:n命令简单来说就是提前读取下一行,覆盖模型空间前一行(并没有删除,因此依然打印至标准输出),如果命令未执行成功(并非跳过:前端条件不匹配),则放弃之后的任何命令,并对新读取的内容,重头执行sed。
n处理流程如下:
例子
[[email protected] ~]# cat num.txt 1 2 3 4 5
例子
[[email protected] ~]# cat num.txt 1 2 3 4 5
打印偶数行
sed -n ‘n;p‘ num.txt 2 4
解析:
读取1到模式空间
执行命令n
读取2并覆盖到模式空间
执行命令p
输出2
立即执行下一循环
读取3到模式空间
执行命令n
读取4并覆盖到模式空间
执行命令p,过程如下
输出4
最后一行,5的具体过程如下
读取5进模式空间
运行命令n,不过读取不到下一行
因为读不到,所以sed退出所有的命令
已经是文件尾,sed结束运行。
打印机奇数行
sed -n ‘$!N;P‘ num.txt 1 3 5
解析
读取1,$!条件满足(不是尾行),执行N命令,得出1\n2,执行P,打印得1,读取3,$!条件满足(不是尾行),执行N命令,得出3\n4,执行P,打印得3,读取5,$!条件不满足,跳过N,执行P,打印得5
d和D
d:删除当前模式空间内容(不在传至标准输出),并放弃之后的命令,并对新读取的内容,重头执行 sed。
D:删除当前模式空间开端至\n的内容(不在传至标准输出),放弃之后的命令,但是对剩余模式空间重 新执行sed。
[[email protected] ~]# cat num.txt 1 2 3 4 5
打印奇数行
[[email protected] ~]# sed ‘n;d‘ num.txt 1 3 5
解析:
读取1,执行n,打印1至标准输出,得出2,执行d,删除2,得空,以此类推,读取3,执行n,打印3至标准输出,得出4,执行d,删除4,得空,但是读取5时,因为n无法执行,所以d不执行。因无-n参数,故输出1\n3\n5;
读取文本的最后一行
[[email protected] ~]# sed ‘N;D‘ num.txt 5
注释:读取1,执行N,得出1\n2,执行D,得出2,执行N,得出2\n3,执行D,得出3,依此类推,得出5,执行N,条件失败退出,因无-n参数,故输出5
注意:
d命令在运行后会直接执行下一循环,所以它并不会执行之后的命令和打印模式空间;例如:在d命令后使用a----将不执行。
[[email protected] ~]# sed ‘n;d;a----‘ num.txt 1 3 5
h和H g和G
h:将当前模式空间中内容覆盖至保持空间
H:将当前模式空间中的内容追加至保持空间
g:将当前保持空间中内容覆盖至模式空间
G:将当前保持空间中的内容追加至模式空间
例子
[[email protected] ~]# cat num.txt 1 2 3 4 5
单独使用h
[[email protected] ~]# sed ‘h‘ num.txt 1 2 3 4 5
将当前的内容复制到保持空间,默认只输出模式空间的内容;
[[email protected] ~]# sed ‘G‘ num.txt 1 2 3 4 5
将保持空间的内容追加到当前模式空间;由于保持空间是空的;因此追加的结果是在每行的后面添加一个空行;
例子
将所有行倒数输出
[[email protected] ~]# sed ‘1!G;h;$!d‘ num.txt 5 4 3 2 1
解析:
读取第一行;匹配1!G,因此不会把保持空间的内容复制到模式空间,当前内容为1;执行h,第一行的内容(1)放到保持空间;执行$!d不是最后一行,删除模式空间内容;
第一行执行后结果:模式空间内容为空,保持空间内容1(如图)
读取第二行,执行1!G,匹配1!G,将保持空间追加到模式空间
执行h复制模式空间的内容放到保持空间
执行$!d不是最后一行,删除
读取第三行,执行1!G,匹配1!G,将保持空间追加到模式空间
执行h复制模式空间的内容放到保持空间
执行$!d不是最后一行,删除
读取第四行,执行1!G,匹配1!G,将保持空间追加到模式空间
执行h复制模式空间的内容放到保持空间
执行$!d不是最后一行,删除
读取最后一行,执行1!G,匹配1!G,将保持空间追加到模式空间
执行h复制模式空间的内容放到保持空间
因为是最后一行,不执行$!d;结果如下
[[email protected] ~]# sed ‘1!G;h;$!d‘ num.txt 5 4 3 2 1
例子
[[email protected] ~]# cat num.txt 1 2 3 4 5
在倒数第二行加上“;”
[[email protected] ~]# sed ‘$!N;$!P;$!D;s/\(\n\)/;\n/‘ num.txt 1 2 3 4; 5
解析:
第一行1读入,匹配$!N;变成1\n2,
匹配$!P;变成
1
1\n2
匹配$!D
变成
1
2
由于没有\n;因此s/\(\n\)\;\n/这一条不执行;
第二次读入,匹配$!N;变成
1
2\n3
匹配$!P;变成
1
2
2\n3
匹配$!D
变成
1
2
3
第三次读入,匹配$!N;变成
1
2
3\n4
匹配$!P;变成
1
2
3
3\n4
匹配$!D
变成
1
2
3
4
第三次读入,匹配$!N;变成
1
2
3
4\n5
不匹配$!P;因此不执行
不匹配匹配$!D
匹配到s/\(\n\)/;\n/ 因此后面变加了“;”
sed ‘$!N;$!P;$!D;s/\(\n\)/;\n/‘ num.txt
替换 | s | [address]s/pattern/replacement/flags | 替换匹配的内容 |
删除 | d | [address]d | 删除匹配的行 |
插入 | i |
[line-address]i\
text |
在匹配行的前方插入文本 |
追加 | a |
[line-address]a\
text |
在匹配行的后方插入文本 |
行替换 | c |
[address]c\
text |
将匹配的行替换成文本text |
打印行 | p | [address]p | 打印在模式空间中的行 |
打印行号 | = | [address]= | 打印当前行行号 |
打印行 | l | [address]l | 打印在模式空间中的行,同时显示控制字符 |
转换字符 | y | [address]y/SET1/SET2/ | 将SET1中出现的字符替换成SET2中对应位置的字符 |
读取下一行 | n | [address]n | 将下一行的内容读取到模式空间 |
读文件 | r | [line-address]r file | 将指定的文件读取到匹配行之后 |
写文件 | w | [address]w file | 将匹配地址的所有行输出到指定的文件中 |
退出 | q | [line-address]q | 读取到匹配的行之后即退出 |