sed总结

由于之前写过sed方面的博文,现在只做些总结和给出一些例子

sed处理文件图解

sed command file


[rocrocket@rocrocket programming]$ cat roc.txt
test 1
test2
testtest
XtestX
BBtest
[rocrocket@rocrocket programming]$ sed ‘/2/d’ roc.txt
test 1
testtest
XtestX
BBtest

此例子是利用sed来删除roc.txt文件里含有字符“2”的行。大家看到了,例子很简单,这个命令的command部分是/2/d,而且它是用单引号括起来的。你也一定要学着这样做,只要用到sed,别忘了用单引号将command部分括起来。

/2/d中的d表示删除,意思就是说只要某行含有字符2,则删除之。(你一定没忘记,sed所谓的删除都是在模式空间中执行的,而原文件roc.txt毫发无损)



想实现类似于cut -d : -f 1 /etc/passwd的效果,用sed怎么做呢?(cut用法参见《cut命令》-linux命令五分钟系列之十九

[rocrocket@rocrocket programming]$ head -n 5 /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

[rocrocket@rocrocket programming]$ head -n 5 /etc/passwd|sed 's/:.*$//'
root
bin
daemon
adm
lp


看到了吧,我们使用的command是’s/:.*$//’,其中的正则表达式s///是替换的经典格式,如果你不太了解,可以看看我之前的一篇博客专题文章,讲述的就是替换的艺术:《vi中的替换艺术》-linux命令五分钟系列之十一

稍作解释: s/:.*$//

:.*$     ------->>>匹配及其后任意个字符为 ----->     //  ------>  空格


command:

 command部分感觉很复杂,能给稍微总结一下么?

command部分是这样,可以分为两部分,一部分是确定范围部分,一部分是处理方式部分。

确定范围部分可以分为两种方式:

1 指定行数:例如3,5表示第3、第4和第5行;5,$表示第5行至最后一行;

2 用模式匹配进行指定:例如/^[^dD]/表示匹配行首不是以d或D开头的行等等。

处理方式部分呢,有很多命令可用,介绍几个最常用的吧:

d:表示删除行

p:打印该行

r:读取指定文件的内容

w:写入指定文件

a\:在下面插入新行新内容

--

例一 显示test文件的第10到20行:sed -n ’10,20p’ test

例二 将所有以d或D开头的行的所有小写x变为大写X:sed ‘/^[dD]/s/x/X/g’ test

例三 删除每行最后的两个字符:sed ‘s/..$//’ test

(有人会问用sed ‘/..$/d’ test为什么不行? 这是因为/..$/表示匹配所有末尾含有两个字符的行,然后删除这样的行,显然这是错误的)

例四 删除每一行的前两个字符:sed ‘s/..//’ test

[root@centos-fuwenchao tmp]# more test 
abgdfgdfgdfgdfgdgdf
cdhdfhfghgf
efgbdfghdfhghd:
[root@centos-fuwenchao tmp]# sed s/..// test 
gdfgdfgdfgdfgdgdf
hdfhfghgf
gbdfghdfhghd:
[root@centos-fuwenchao tmp]# sed s/^..// test 
gdfgdfgdfgdfgdgdf
hdfhfghgf
gbdfghdfhghd:
[root@centos-fuwenchao tmp]# sed s/..$// test 
abgdfgdfgdfgdfgdg
cdhdfhfgh
efgbdfghdfhgh
[root@centos-fuwenchao tmp]# 

^出现在字符集才表示脱字符,出现在正则表达式中是锚位符。

例五 给某些字符串后面插入些内容

[rocrocket@rocrocket programming]$ cat mysed.txt
Beijing
London[rocrocket@rocrocket programming]$ sed ‘s/B.*/&2008/’ mysed.txt
Beijing2008
London


这个命令的作用是将包含’B.*’的地方后面加上2008四个字符。这个命令里用到了&字符,这是一个技巧,高手和菜鸟比,这些技巧很重要哦。&表示“被匹配的部分”,在这里就是’Beijing’喽!

[root@centos-fuwenchao tmp]# sed -n /4/p num.txt 
4
[root@centos-fuwenchao tmp]# sed  /4/p num.txt 
1
2
3
4
4
5
6
7
8
[root@centos-fuwenchao tmp]# sed  '/4/p' num.txt 
1
2
3
4
4
5
6
7
8
[root@centos-fuwenchao tmp]# sed -n '/4/p' num.txt 
4
[root@centos-fuwenchao tmp]# more num.txt 
1
2
3
4
5
6
7
8
[root@centos-fuwenchao tmp]# sed 's/g$/&2009/' test 
abgdfgdfgdfgdfgdgdf
cdhdfhfghgf
efgbdfghdfhghd:
[root@centos-fuwenchao tmp]# sed 's/f$/&2009/' test 
abgdfgdfgdfgdfgdgdf2009
cdhdfhfghgf2009
efgbdfghdfhghd:
[root@centos-fuwenchao tmp]# sed s/f$/&2009/ test 
[1] 5960
-bash: 2009/: No such file or directory
[root@centos-fuwenchao tmp]# sed: -e expression #1, char 5: unterminated `s' command
^C
[1]+  Exit 1                  sed s/f$/
[root@centos-fuwenchao tmp]# 

所以最好还是给command部分加上单引号吧

例六 将行的第一个Beijing后加上2008,在最后一个Beijing后加上2008

[rocrocket@rocrocket programming]$ cat mysed.txt
Beijing Beijing Beijing Beijing
London London London London
[rocrocket@rocrocket programming]$ sed ‘s/\(Beijing\)\(.*\)\(Beijing\)/\12008\2\32008/’ mysed.txt
Beijing2008 Beijing Beijing Beijing2008
London London London London

--

[root@centos-fuwenchao tmp]# sed 's/\(Beijing\)\(.*\)\(Beijing\)/\12008\2\32008/' sed.txt 
Beijing2008 Beijing Beijing Beijing2008
London London London London
[root@centos-fuwenchao tmp]# sed 's/\(^Beijing\)\(Beijing$\)/\12008\22008/' sed.txt 
Beijing Beijing Beijing Beijing
London London London London
[root@centos-fuwenchao tmp]# sed   's/\(^Beijing\)\(Bttttt$\)/\12008\22008/' sed.txt 
Beijing Beijing Beijing Beijing
London London London London
[root@centos-fuwenchao tmp]# 


这个命令稍显复杂,其中用到了一个技巧,就是预存储,即被\(和\)括起来的匹配内容会被按顺序存储起来,存储到\1、\2…里面。这样你就可以使用\加数字来调用这些内容了。这个例子就是使用了这个技巧,分别存储了三个内容,分别为匹配Beijing、匹配.*和匹配Beijing。

你可能会问,我如果想在第一个t前加上M,在第二个t前加上N,怎么做呢?

这个就需要使用正则表达式的非贪婪算法了,一般是在?、+、*、{n}、{m,}、{m,n}的后面紧跟一个?,就会使匹配从贪婪算法变成非贪婪算 法,但是遗憾的是,sed并不支持这种非贪婪算法,所以我们无法使用sed实现这种想法,只能另寻其他工具了。这也算是sed的一个遗留问题吧。


例七 可以用模式来定位行范围

[rocrocket@rocrocket programming]$ cat mysed.txt
Beijing 2003
Beijing 2004
Beijing 2005
Beijing 2006
Beijing 2007
Beijing 2008
Beijing 2007
[rocrocket@rocrocket programming]$ sed -n ‘/2005/,/2007/p’ mysed.txt
Beijing 2005
Beijing 2006
Beijing 2007


我们使用/2005/来匹配行范围的首行,用/2008/来匹配行范围的最尾行。可以看到,在匹配尾行时,只要遇到符合要求的行,即停止,不会再继续向后匹配了。(只是匹配到第一个2007,并没有匹配到第二个2007)

例八 用-e选项来设置多个command

还记得command部分吧,现在我告诉你,sed命令可以包含不只一个的command,但是当包含超过一个的command的时候,必须在每个command前面加上选项-e。

[rocrocket@rocrocket programming]$ sed -n -e ’1,2p’ -e ’4p’ mysed.txt
Beijing 2003
Beijing 2004
Beijing 2006


虽然这个例子看似是为了使用-e而使用-e,但是-e在有些时候是很有用的。相信我,呵呵:)

记住,-e后面必须立即接command,不允许再夹杂其他的选项了。


例九 可以使用-f来设定包含command的文件名称

如果你的command很长,那么可以将其写在文件里,然后使用-f来设定这个文件作为command部分:

[rocrocket@rocrocket programming]$ cat callsed
/2004/,/2006/p
[rocrocket@rocrocket programming]$ sed -n -f callsed mysed.txt
Beijing 2004
Beijing 2005
Beijing 2006


两个命令就讲清楚了-f的用法。相信你能看懂

例十 如果设定了很多-e的command,它们的执行顺序是怎样的呢?

[rocrocket@rocrocket programming]$ cat mysed.txt
Beijing 2003
Beijing 2004
Beijing 2005
Beijing 2006Beijing 2007
Beijing 2008
[rocrocket@rocrocket programming]$ sed -e ‘s/Beijing/London/g’ -e ‘/Beijing/d’ mysed.txt
London 2003
London 2004
London 2005
London 2006
London 2007
London 2008


后一个-e中包含了删除Beijing所在行,但是最后的结果却是所有行都输出了,其实这就是由执行顺序导致的,第一个-e已经将Beijing都替换成了London了,所以怪不得第二个-e找不到Beijing了。

例十一 读取一个特定文件的内容,将其插入到本文件指定的地方:

[rocrocket@rocrocket programming]$ cat ins.txt
====China====
[rocrocket@rocrocket programming]$ cat mysed.txt
Beijing 2003
Beijing 2004
Beijing 2005
Beijing 2006
Beijing 2007
Beijing 2008
[rocrocket@rocrocket programming]$ sed ‘/2005/r ins.txt’ mysed.txt
Beijing 2003
Beijing 2004
Beijing 2005
====China====
Beijing 2006
Beijing 2007
Beijing 2008


此命令用于在含有2005的行下面插入ins.txt文件的内容。

例十二 将某些指定行写入到特定文件中

[rocrocket@rocrocket programming]$ sed ‘/200[4-6]/w new.txt’ mysed.txt
Beijing 2003
Beijing 2004
Beijing 2005
Beijing 2006
Beijing 2007
Beijing 2008
[rocrocket@rocrocket programming]$ cat new.txt
Beijing 2004
Beijing 2005
Beijing 2006


看,w new.txt表示将含有2004、2005、2006的行写入到new.txt文件中。

例十三 使用a\在特定行“下面”插入特定内容

[rocrocket@rocrocket programming]$ cat new.txt
Beijing 2004
Beijing 2005
Beijing 2006
[rocrocket@rocrocket programming]$ sed ‘/2004/a\China’ mysed.txt
Beijing 2003
Beijing 2004
China
Beijing 2005
Beijing 2006
Beijing 2007
Beijing 2008


使用a\然后加上需要加的内容即可。

例十四 使用i\在特定行“上面”插入特定内容

[rocrocket@rocrocket programming]$ sed ‘/2004/i\China’ mysed.txt
Beijing 2003
China
Beijing 2004
Beijing 2005
Beijing 2006
Beijing 2007
Beijing 2008


例十五 替换特定字符

[root@centos-fuwenchao tmp]# more tihuan 
Beijing 2004
Beijing 2005
Beijing 2006
Beijing 2007
Beijing 2008
[root@centos-fuwenchao tmp]# sed 'y/ei/EI/' tihuan 
BEIjIng 2004
BEIjIng 2005
BEIjIng 2006
BEIjIng 2007
BEIjIng 2008
[root@centos-fuwenchao tmp]# 

呵呵,看出y与s的区别了吧!

[root@centos-fuwenchao tmp]# sed 's/ei/EI/' tihuan 
BEIjing 2004
BEIjing 2005
BEIjing 2006
BEIjing 2007
BEIjing 2008
[root@centos-fuwenchao tmp]# 


使用了y就表示将第一栏的每个字符都替换为相对应的第二栏的字符。

例十六 对匹配行的下一行进行处理

[rocrocket@rocrocket programming]$ cat mysed.txt
Beijing 2003
Beijing 2004
Beijing 2005
Beijing 2006
Beijing 2007
Beijing 2008
[rocrocket@rocrocket programming]$ sed ‘/2004/{n;y/eijng/EIJNG/;}’ mysed.txt
Beijing 2003
Beijing 2004
BEIJING 2005
Beijing 2006
Beijing 2007
Beijing 2008
[root@centos-fuwenchao tmp]# sed '/2004/{n;s/2005/9999/;}' tihuan 
Beijing 2004
Beijing 9999
Beijing 2006
Beijing 2007
Beijing 2008
[root@centos-fuwenchao tmp]# 


这个例子就是找含有2004的行,然后将它下面的一行中的eijng替换为大写的EIJNG。这里面的“n;”起到了“移至下一行”的作用。n背后的含义其实是将下一行放到模式空间中去。

[rocrocket@rocrocket programming]$ cat mysed.txt
Beijing 2003
Beijing 2004
Beijing 2005
Beijing 2006
Beijing 2007
Beijing 2008
[rocrocket@rocrocket programming]$ sed ‘/200/{n;y/eijng/EIJNG/;}’ mysed.txt
Beijing 2003
BEIJING 2004
Beijing 2005
BEIJING 2006
Beijing 2007
BEIJING 2008


这个例子更加典型,你可以发现,BEIJING是隔行出现的。你知道为什么么?不说答案了,相信你能自己思考出来!

ps:sed的流艺术系列到这里就结束了:)

ps:其实sed的学问还很大,正则表达式也有很多需要学习的地方,我也在学习中…这个小系列,就当抛砖引玉了,希望对你有用!

over~




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值