在例5中,每一行都被打印了2次,原因是在模式空间的时候被打印了一次,然后处理完成之后,在标准输出又被打印了一次,所以自然会显示出两次。如果使用-n,则仅仅打印的模式空间的内容。
a test:在行后面追加文本"test",可以使用\n实现多行追加
[root@localhost ~]# sed '1 a hi i am here\nhey'poetry1)Never give up,
hi i am here
hey2)Never lose hope.3)Always have faith,4)It allows you to cope.5)Trying times will pass,6)As they always do.7)Just have patience,8)Your dreams will come true.9)So put on a smile,10)You'll live through your pain.
11)Know it will pass,12)And strength you will gain
i test:在 行前面插入文本test,支持使用\n实现多行插入
[root@localhost ~]# sed '2i hi i am here\nhey'poetry1)Never give up,
hi i am here
hey2)Never lose hope.3)Always have faith,4)It allows you to cope.5)Trying times will pass,6)As they always do.7)Just have patience,8)Your dreams will come true.9)So put on a smile,10)You'll live through your pain.
11)Know it will pass,12)And strength you will gain
c test:把匹配到的行替换为此处指定的行
[root@localhost ~]# sed '2c hi i am here'poetry1)Never give up,
hi i am here3)Always have faith,4)It allows you to cope.5)Trying times will pass,6)As they always do.7)Just have patience,8)Your dreams will come true.9)So put on a smile,10)You'll live through your pain.
11)Know it will pass,12)And strength you will gain
w /path/to/somefile:保存模式空间中匹配到的内容到指定的文件中
[root@localhost ~]# sed '/So/ w /tmp/poetry'poetry1)Never give up,2)Never lose hope.3)Always have faith,4)It allows you to cope.5)Trying times will pass,6)As they always do.7)Just have patience,8)Your dreams will come true.9)So put on a smile,10)You'll live through your pain.
11)Know it will pass,12)And strength you will gain
[root@localhost~]#
[root@localhost~]# cat /tmp/poetry9)So put on a smile,
r /path/from/somefile:读取指定文件的内容至当前文件中被模式匹配的行后面
[root@localhost ~]# catpoetry2.txt13)yes! I can![root@localhost~]# sed '12 r poetry2.txt'poetry1)Never give up,2)Never lose hope.3)Always have faith,4)It allows you to cope.5)Trying times will pass,6)As they always do.7)Just have patience,8)Your dreams will come true.9)So put on a smile,10)You'll live through your pain.
11)Know it will pass,12)And strength you will gain13)yes! I can!
=:为模式匹配到的行打印行号,打印在行的上面
[root@localhost ~]# sed '/Never/ ='poetry1
1)Never give up,2
2)Never lose hope.3)Always have faith,4)It allows you to cope.5)Trying times will pass,6)As they always do.7)Just have patience,8)Your dreams will come true.9)So put on a smile,10)You'll live through your pain.
11)Know it will pass,12)And strength you will gain
!:条件取反
[root@localhost ~]# sed '/Never/ !d'poetry #不删除被默认匹配的行1)Never give up,2)Never lose hope.
s///:查找替换,分割符可以自定义,比如使用s@@@flag或者s###flag,默认会替换被匹配的第一个位置,但是可以添加替换标记:
s///g:全局替换
[root@localhost ~]# catpoetry1)Never give up,2)Never lose hope.3)Always have faith,4)It allows you to cope.5)Trying times will pass,6)As they always do.7)Just have patience,8)Your dreams will come true.9)So put on a smile,10)You'll live through your pain.
11)Know it will pass,12)And strength you will gain
[root@localhost~]# sed 's/\/your/g'poetry1)Never give up,2)Never lose hope.3)Always have faith,4)It allows your to cope.5)Trying times will pass,6)As they always do.7)Just have patience,8)Your dreams will come true.9)So put on a smile,10)You'll live through your pain.
11)Know it will pass,12)And strength your will gain
View Code
sed默认支持的基本的正则表达式,使用-r, --regexp-extended选项可以支持扩展的正则表达式。
练习1:删除/boot/grub2/grub.cfg文件中所有以空白字符开头的行的行首的所有空白字符
[root@localhost ~]# sed -r 's@^[[:space:]]+@@g' /boot/grub2/grub.cfg
View Code
练习2:删除/etc/fstab文件中所有以#开头的行的行首的#号及#后面的所有空白字符
[root@localhost ~]# sed 's/^#[[:space:]]*//g' /etc/fstab
View Code
练习3:输出一个目录给sed,取出其目录,类似于dirname
[root@localhost ~]# echo "/var/log/messages" | sed -r 's@[^/]+/?$@@'
/var/log/[root@localhost~]#
[root@localhost~]# echo "/var/log/messages/" | sed -r s@[^/]+/?$@@'
/var/log/
高级编辑命令
sed还有一些高级的命令,会用到之前说到的保持空间。
举一些例子来看一下吧!
[root@localhost ~]# catpoetry1)Never give up,2)Never lose hope.3)Always have faith,4)It allows you to cope.5)Trying times will pass,6)As they always do.7)Just have patience,8)Your dreams will come true.9)So put on a smile,10)You'll live through your pain.
11)Know it will pass,12)And strength you will gain
可以自己先思考一下答案,再点开:
[root@localhost ~]# sed -n 'n;p'poetry #只显示偶数行2)Never lose hope.4)It allows you to cope.6)As they always do.8)Your dreams will come true.10)You'll live through your pain.
12)And strength you will gain
sed -n 'n;p' poetry
[root@localhost ~]# sed '1!G;h;$!d'poetry #逆序显示12)And strength you will gain11)Know it will pass,10)You'll live through your pain.
9)So put on a smile,8)Your dreams will come true.7)Just have patience,6)As they always do.5)Trying times will pass,4)It allows you to cope.3)Always have faith,2)Never lose hope.1)Never give up,
sed '1!G;h;$!d' poetry
[root@localhost ~]# sed '$!d' poetry #只保留最后一行,类似tail -1
12)And strength you will gain
sed '$!d' poetry
[root@localhost ~]# sed '$!N;$!D'poetry #取出最后两行11)Know it will pass,12)And strength you will gain
sed '$!N;$!D' poetry
[root@localhost ~]# sed 'G'poetry #在每一行的后面添加一个空白行1)Never give up,2)Never lose hope.3)Always have faith,4)It allows you to cope.5)Trying times will pass,6)As they always do.7)Just have patience,8)Your dreams will come true.9)So put on a smile,10)You'll live through your pain.
11)Know it will pass,12)And strength you will gain
sed 'G' poetry
这些都是一些高级的用法,在工作中用的可能比较少,因为有的结果完全可以用其他简单的命令去实现。
循环和分支
sed最牛逼之处莫过于这个了,sed提供了一个循环和分支工来控制程序的执行流程。
循环
sed循环的工作原理类似于现代编程语言中的goto语句。
定义sed的标签:
:label
跳转到标签的位置,使用b命令后面跟着标签名即可,下面我们来看一个具体的实例:
[root@localhost ~]# catteleplay
剧名:白夜追凶
评分:9.0剧名:秘密深林
评分:9.3剧名:权利的游戏第七季
评分:9.3剧名:请回答1988
评分:9.6[root@localhost~]# sed -n 'h;n;H;x
s@\n@,@/请回答/!b label
s@^@---@
:label
p'teleplay
剧名:白夜追凶,评分:9.0剧名:秘密深林,评分:9.3剧名:权利的游戏第七季,评分:9.3
---剧名:请回答1988,评分:9.6
分析:
由于命令很长,我们可以将命令分行来写,当然也可以写在一行里面:
1.h;n;H;x:将第一行内容读取到模式空间,执行h,将模式空间的内容覆盖至保持空间,执行n,从文件中读取第二行覆盖至模式空间,执行H,将模式空间的内容追加至保持空间,执行x,将保持空间的内容和模式空间调换;(这里得到的结果就是模式空间中存在两行);
2.s@\n@,@,将换行符替换为逗号;这样原来的两行就变成了一行;
3./请回答/!b label,判断这一行中是否有“请回答”三个字符,如果没有则直接跳到":label",然后执行打印"p",打印模式空间中的内容,如果有则执行"s@^@---@",将在行首添加字符"---"。
这样一来,只有"剧名:请回答1988,评分:9.6"被匹配,然后进行了行首的替换操作。
分支
可以使用t来创建分支。使用t命令跳转到指定的标签,一样我们来看一个例子:
[root@localhost ~]# sed -n '>h;n;H;x> s/\n/,/
>:loop> /白夜追凶/s/^/-/
> /-----/!t loop> p'teleplay
-----剧名:白夜追凶,评分:9.0剧名:秘密深林,评分:9.3剧名:权利的游戏第七季,评分:9.3剧名:请回答1988,评分:9.6
分析:
由于命令很长,我们可以将命令分行来写,当然也可以写在一行里面:
1:h;n;H;x:将第一行内容读取到模式空间,执行h,将模式空间的内容覆盖至保持空间,执行n,从文件中读取第二行覆盖至模式空间,执行H,将模式空间的内容追加至保持空间,执行x,将保持空间的内容和模式空间调换;(这里得到的结果就是模式空间中存在两行);
2:s@\n@,@,将换行符替换为逗号;这样原来的两行就变成了一行;
3::loop:定义了一个loop标签;
4:/白夜追凶/s/^/-/:是否匹配模式,如果匹配则在其行首添加一个"-";如果不匹配,则直接打印;
5:/-----/!t loop:是否存在5个"-",如果不存在,则跳到标签loop处,继续执行第4步添加"-",直到满足5个"-",则跳出循环打印。
最后,我们之前的所有的操作,都是没有修改文件的本身的,可以使用 -i 选项来直接修改文件本身,慎用,建议在使用之前,先备份一下文件!
[root@localhost ~]# sed -i '1d'poetry
[root@localhost~]#
[root@localhost~]# catpoetry2)Never lose hope.3)Always have faith,4)It allows you to cope.5)Trying times will pass,6)As they always do.7)Just have patience,8)Your dreams will come true.9)So put on a smile,10)You'll live through your pain.
11)Know it will pass,12)And strength you will gain
总结:sed的确是一个强大的文本处理工具,功能非常丰富,需要在今后的日常使用和工作中不断的熟悉和巩固。