免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 5606 | 回复: 9
打印 上一主题 下一主题

[学习共享] sed-b/t/T/p/P/d/D-smallpboy笔记 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-08-10 09:32 |只看该作者 |倒序浏览
本帖最后由 smallpboy 于 2012-08-24 11:06 编辑

    上次贴了一部分sed的内容,今天把全部的内容都贴出来。这两天没上cu,看到版主及其他大哥们的留言,小弟微微改下语句及排版等。让这文章再混个前排,罪过。罪过。
1、b/t/T的区别
    所谓的标签,其功能就像c++里的“loop:”和“goto”。“b”操作的范例如下:
[smallpboy @local tmp]$ cat file
111
222
[smallpboy @local tmp]$ cat file | sed –n ‘/^1/b f;p;:f;p’
111
222
222
仔细看sed里面的内容,”/^1/b f”这个就是说匹配开头字母是1的,‘b’后面跟的‘f’实际上就想一个旗标,它标志着‘b’操作跳转到哪。这不后面不出现了”:f;p”语句么,‘:f’就是这个旗标,‘p’表示打印pattern space内容。所以,行首如果是‘1’的话,就会跳过一个‘p’操作(第一个被跳过),这样解释能看懂输出结果了吧。
    接下来是t/T的范例:
[smallpboy @local tmp]$ cat file | sed –n ‘s/^1/&/;t f;p;:f;p ’
111
222
222
[smallpboy @local tmp]$ cat file | sed –n ‘s/^1/&/;T f;p;:f;p ’
111
111
222
t/T操作的区别看出来吧?‘t’操作表示前面的‘s/1^/&/’匹配成功,就跳到‘f’那去,‘T’操作则正好跟它相反。‘&’是什么东西?就不告诉你啊,就不告诉你。
    “b/t/T”操作的功能就都说啦,是不是很简单? 对了,如果你不在“b/t/T”后面加上旗标‘f’的话,它默认是直接跳到脚本末尾。你可以试试如下命令:
[smallpboy @local tmp]$ cat file | sed –n ‘s/^1/&/;T;p;:f;p ’
111
111
看清楚哦,‘T’后面可没有‘f’咯,所以当‘T’操作满足时,直接跳到脚本尾了,什么输出都没有。而后面这个‘:f’你尽管保留,有它没它都不影响脚本。

2、p/P操作
    这两个其实没啥说的,‘小p’表示打印pattern space全部内容。‘大P’表示打印pattern space的第一行。看下面的例子:
[smallpboy @local tmp]$ cat file
111
222
[smallpboy @local tmp]$ cat file | sed –n ‘/.*/G;p’        #小p
111

222

[smallpboy @local tmp]$ cat file | sed –n ‘/.*/G;P’       #大p
111
222
‘G’操作你已经很熟悉了吧?是不是把hold space的内容添加到pattern space中?这样,上面的例子能理解了吧。

3、d/D操作
    ‘d’操作没什么好讲的,一股脑将pattern space全部删除,这个‘D’操作就有不少人理解不过来了。好了,看我下面的例子你就清楚啦。
[smallpboy @local tmp]$ seq 4 | sed ‘$!N;d’
[smallpboy @local tmp]$
没有输出?对的,这个好理解吧!‘$!N’意思是如果还没读到最后一行,就继续读入一行(这个不用解释吧,不清楚试试’$!‘、'3!'这些语句去吧。)。
[smallpboy @local tmp]$ seq 4 | sed ‘$!N;D’
[smallpboy @local tmp]$
还是没有输出?对,因为这个‘D’是循环地一行一行删除pattern space内容,如果没有限制它跟‘d’功能是一样的。限制?怎样限制呢?限制什么东西,是pattern space还是文本行?
[smallpboy @local tmp]$ seq 4 | sed ‘$!N;4D’
1
2
[smallpboy @local tmp]$ seq 4 | sed ‘$!N;3D’
1
2
3
4
上面这两个能理解么?‘4D’意思就是第4行执行‘D’操作(原来限制的对象是文本),即sed你读到第四行的话我就删除pattern space第一行,再删第二行。所以它输出1\n2。我相信第一个你也许能理解,但这第二个真是不好理解啊。对吧?
    ‘3D’ 的意思是sed你读到第3行的话,我执行‘D’操作,很可惜啊。当sed读到第3行后,立刻又执行了‘$!N’操作,所以执行“3D”时,sed已经读到第4行了。所以这个‘D’不被执行啦。所以输出是上述结果,这下你懂了吧。在这条语句中,奇数行根本就取不到它,你写‘1D‘、’3d‘全判为假。这样,下面的例子你也能理解了。
[smallpboy @local tmp]$ seq 4 | sed ‘N;d’
[smallpboy @local tmp]$ seq 5 | sed ‘N;d’
5
第一个例子没有输出,当sed共读入四行时,他们两行两行配对,所以都被‘d‘了。而第二个例子中,当sed读到第5行后,执行’N‘操作,发现没有了(就算出错了哈),直接跳到脚本尾了。所以,它输出5。不信,你动手试试看啊。
    好了,上面说了一堆,还没有讲到“D”操作。还有一个很重要的问题就是,我就是想要‘D’只删除pattern space的第一行,那要怎么办。man sed里‘D’的解释是:
delete up to the first embedded newline in the pattern space.start next cycle,but skip reading from the input if there is still data in the pattern space.
删除模式空间的第一个新行,开始下一个循环,模式空间有数据的话,不继续读入input数据,也就是继续循环‘D’操作。
[smallpboy @local tmp]$ seq 4 | sed –n ‘$!N;D;p’
2
4
上述命令‘$!N’读入“1\n2”进来,然后执行‘D’操作,删除pattern space第一行,然后‘p’操作把它打印出来。 你也是不是跟我一样想的呢?
可实际上,上述语句并没有任何输出。‘D’操作会循环执行删除pattern space一行的动作,知道pattern space没有数据为止。所以,pattern 里面的数据都被删光了。
再来看下面的例子:
[smallpboy @local tmp]$ seq 4 | sed –n ‘N;2D;p’
2
3
[smallpboy @local tmp]$ seq 4 | sed –n ‘N;3D;p’
1
2
3
4
不好意思,先把难的放第一个了。这个真的不好懂啊,我弄了好几小时才把‘D’弄明白啊。
    ‘sed’先读入‘1’(这算是sed的input,和'N'操作的input要分开),然后执行‘N’,读入‘2’。然后‘2D’,表示对第2行‘D’操作,这时,文本确实已经读到第2行,所以‘2D’成功执行把pattern space里‘1\n’给删除了。然后,注意了啊,‘D’操作并没有结束啊,pattern space还有‘2’呢,这时它继续从脚本开头执行,也就是‘N’操作,这时把‘3’读入(你可能会问,不是pattern space不为空,就不读input吗?你说的对啊,但是sed它确实没有主动读入input啊,而是‘N’操作读入了下一行,你把‘N’换成别的,那也就没有input数据了。)。好了,继续讲。读入‘3’后,到第三行了,‘2D’为假了,所以不执行‘D’操作了,终于轮到‘p’操作了,这时pattern space的结果是不是‘2\n3’啊,被打印出来。接着,sed主动读入‘4’,然后执行‘N’操作,发现没有下一行了,出错了就直接跳到脚本末尾,所以‘p’操作都不执行了。这样,‘4’也打印不出了。不信的话,你试试下面的脚本就能打印出‘4’来了。
[smallpboy @local tmp]$ seq 4 | sed –n ‘$!N;2D;p’
    在这里我插一句,很多人就是因为测试时传进来参数的个数---奇数和偶数不同而导致产生不同的结果。
[smallpboy @local tmp]$ seq 5 | sed ‘N;d’
5
上述这个结果,居然出现了‘5’,看懂我前面讲的同学,你一定已经知道怎么回事了。输出的‘5’,它不是‘D’没有删除pattern space,而是执行‘$!N’时出错,直接跳过‘D’操作了。
说到这,‘D’操作也说完了。总的来说,注意的无非一点:

    * 当类似‘N;2D;P’这样,‘D’满足条件的就会跳到脚本开头执行脚本,在这里也就是执行‘N’操作,然后再‘2D’操作,当‘2D’不满足条件后,才执行‘p’。

上回说到sed实现rev功能时,最后说到‘//D’操作真心不懂。现在咱再从头开始捋一遍。
    整个语句:sed ‘/\n/!G;s/\(.\)\(.*\n\)/&\2\1/;//D;s/.//;’
   
    “/\n/!G;”在stdin中没有找到\n,就主动添上\n。
    “s/\(.\)\(.*\n\)/&\2\1/;”中\(.\)先匹配一个字符,再匹配剩下所有字符。“&”指整个pattern space,\2和\1想必你也知道是什么东东。
[smallpboy @local tmp]$ cat file
123
file文件中“123”(上回是‘123\n’,其实你用’vi’编辑没有敲回车的话它并没有‘\n’,加不加‘\n’其实是有关系的,这里我不能再单独讲他们的区别,思维很混乱。)执行‘/\n/!G’,变成‘123\n’,然后执行‘s/\(.\)\(.*\n\)/&\2\1/;’
[smallpboy @local tmp]$ cat file | sed ‘/\n/!G;s/\(.\)\(.*\n\)/&\2\1/;’
123
23
1
上面可能读懂?“123\n”分别被匹配为\1(1)和\2(23\n),所以&\2\1的结果为‘123\n23\n1’。
[smallpboy @local tmp]$ cat file | sed ‘/\n/!G;s/\(.\)\(.*\n\)/&\2\1/;//D’
上面说到第一次执行s….后,pattern space为‘123\n23\n1’,然后要执行‘//D’命令了,结果为23\n1。
然后到开头继续执行/\n/!G;,pattern space(旧的)不变,然后执行s….后,新的pattern space为23\n3\n21(\1为2,\2为3\n,&为23\n),然后执行//D,结果为3\n21。
再执行/\n/!G;,pattern space(下一操作s….会产生新的pattern space把这个给覆盖)不变,执行s….,结果变为3\n\n321(\1为3,\2为\n,&为3\n),再执行//D操作,结果为\n321。
继续执行/\n/!G;,pattern space不变,然后执行s….,发现匹配不了。执行//D操作,‘//’不匹配,也不执行‘D’操作。所以‘sed ‘/\n/!G;s/\(.\)\(.*\n\)/&\2\1/;//D’’的结果为‘\n321’,最后执行‘s/.//’操作,所以最终打印出‘321’。
[smallpboy @local tmp]$ cat file | sed –n ‘/\n/!G;s/\(.\)\(.*\n\)/&\2\1/;P;//D’  
123
23
3

[smallpboy @local tmp]$ cat file | sed ‘/\n/!G;s/\(.\)\(.*\n\)/&\2\1/;//D’

321
最后的,这个’//D’并没有匹配上‘\n321’,我到现在也不明白‘//D’这两个‘//’是什么意思,是匹配空字符吗?希望知道的朋友能在下面跟帖留言,大家一起互帮互助。

论坛徽章:
15
2015年辞旧岁徽章
日期:2015-03-03 16:54:15双鱼座
日期:2015-01-15 17:29:44午马
日期:2015-01-06 17:06:51子鼠
日期:2014-11-24 10:11:13寅虎
日期:2014-08-18 07:10:55酉鸡
日期:2014-04-02 12:24:51双子座
日期:2014-04-02 12:19:44天秤座
日期:2014-03-17 11:43:36亥猪
日期:2014-03-13 08:13:51未羊
日期:2014-03-11 12:42:03白羊座
日期:2013-11-20 10:15:18CU大牛徽章
日期:2013-04-17 11:48:45
2 [报告]
发表于 2012-08-10 09:41 |只看该作者
欢迎欢迎。多给大家回答回答就好。

论坛徽章:
5
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:50:282015年亚洲杯之朝鲜
日期:2015-03-13 22:47:33IT运维版块每日发帖之星
日期:2016-01-09 06:20:00IT运维版块每周发帖之星
日期:2016-03-07 16:27:44
3 [报告]
发表于 2012-08-10 10:02 |只看该作者


首先,支持LZ的分享精神。

没有仔细看完,写的比较粗,有些地方没有讲清楚。

另外,最好排版好,这也是很重要的。

论坛徽章:
16
IT运维版块每日发帖之星
日期:2015-10-02 06:20:00IT运维版块每月发帖之星
日期:2015-09-11 19:30:52IT运维版块每周发帖之星
日期:2015-09-11 19:20:31IT运维版块每日发帖之星
日期:2015-08-26 06:20:00每日论坛发贴之星
日期:2015-08-20 06:20:00IT运维版块每日发帖之星
日期:2015-08-20 06:20:002015年辞旧岁徽章
日期:2015-03-03 16:54:15金牛座
日期:2014-05-04 16:58:09双子座
日期:2013-12-17 16:44:37辰龙
日期:2013-11-22 15:20:59狮子座
日期:2013-11-18 22:55:08射手座
日期:2013-11-12 10:54:26
4 [报告]
发表于 2012-08-10 17:04 |只看该作者
看的晕乎乎的,明天看吧。今天整点别的。

论坛徽章:
3
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:51:162015年亚洲杯之阿曼
日期:2015-04-07 20:00:59
5 [报告]
发表于 2012-08-11 11:19 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
6 [报告]
发表于 2012-08-13 11:06 |只看该作者
本帖最后由 quanzhou722 于 2012-08-13 12:00 编辑

这个最后的 //D 真是不好理解。到底是匹配啥了?

  //D  是不是匹配到空行结束D命令?要不然有点解释不通


论坛徽章:
16
IT运维版块每日发帖之星
日期:2015-10-02 06:20:00IT运维版块每月发帖之星
日期:2015-09-11 19:30:52IT运维版块每周发帖之星
日期:2015-09-11 19:20:31IT运维版块每日发帖之星
日期:2015-08-26 06:20:00每日论坛发贴之星
日期:2015-08-20 06:20:00IT运维版块每日发帖之星
日期:2015-08-20 06:20:002015年辞旧岁徽章
日期:2015-03-03 16:54:15金牛座
日期:2014-05-04 16:58:09双子座
日期:2013-12-17 16:44:37辰龙
日期:2013-11-22 15:20:59狮子座
日期:2013-11-18 22:55:08射手座
日期:2013-11-12 10:54:26
7 [报告]
发表于 2012-08-21 11:28 |只看该作者
‘sed’先读入‘1’,然后执行‘N’,读入‘2’。然后‘2D’,表示对第2行‘D’操作,这时,确实sed已经读到第2行,所以‘2D’成功执行把pattern space里‘1\n’给删除了。然后,注意了啊,‘D’操作并没有结束啊,pattern space还有‘2’呢,这时它继续‘N’操作啊,这时把‘3’读入(你可能会问,不是pattern space不为空,就不读input吗?你说的对啊,但是sed它确实没有主动读入input啊,而是‘N’操作读入了下一行,你把‘N’换成别的,那也就没有input数据了。)。好了,继续讲。读入‘3’后,到第三行了,‘2D’为假了,所以不执行‘D’操作了,终于轮到‘p’操作了,这时pattern space的结果是不是‘2\n3’啊。接着,sed主动读入‘4’,然后执行‘N’操作,发现没有下一行了,出错了就直接跳到脚本末尾,所以‘p’操作都不执行了。这样,‘4’也打印不出了。不信的话,你试试下面的脚本就能打印出‘4’来了

你这里有个问题,当 对第二行'D'操作后,后面不是还有个p吗?应该打印,怎么就直接又N了呢?

论坛徽章:
0
8 [报告]
发表于 2012-08-24 10:24 |只看该作者
D操作如果继续执行的话,是直接再去执行“”里的脚本,‘D’后面的语句只有‘2D’不满足条件时才能执行。所以这个‘p’操作,再第一次并不能被执行。我在‘()’里已经说了。
回复 7# wenhq


   

论坛徽章:
0
9 [报告]
发表于 2012-08-24 10:26 |只看该作者
谢谢block哥支持。我重新修改下。
回复 3# blackold


   

论坛徽章:
3
酉鸡
日期:2014-04-23 17:17:56丑牛
日期:2014-05-08 11:41:302015亚冠之德黑兰石油
日期:2015-08-03 11:14:27
10 [报告]
发表于 2014-12-15 12:34 |只看该作者
mark下
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP