免费注册 查看新帖 |

Chinaunix

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

[学习共享] sed-n/N/g/G/h/H/x……进来顶顶吧 [复制链接]

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

文章前本来有说明的,连续发表了两次,修改过的那篇居然没发表。这算是我学sed的笔记吧,但我故意把语句口语化,也是出于方便大家理解的考虑。本文针对的读者是学习sed的新手,以后我会补充它或是贴出其他的帖子(例如awk的)。谢谢大家的支持哈。 对了,文末的问题还请大牛们帮忙解答啊,我加粗显示了。

     •先讲n/N的区别
ywlscpl大牛这么比喻:
如果sed的模式空间对应awk的$0
N相当于awk的{v=$0;next;$0=v"\n"$0}
n相当于awk的next

用shell来比喻的话
N是:  echo 下一行内容>>模式空间
n是:  echo 下一行内容>模式空间

[smallpboy @local tmp]$ seq 4 | sed ‘n;d’
1
3
pattern space先读入1,然后执行到n,把下一行2读入pattern space中并覆盖原本的1。然后pattern space中的内容(2)被删除(d操作),所以打印出1\n3。
[smallpboy @local tmp]$ seq 5 | sed ‘n;d’          你知道它输出什么吗?
1
3
5
你猜对了吗?
[smallpboy @local tmp]$ seq 4 | sed ‘N;d’
[smallpboy @local tmp]$
什么都没输出?对,你没看错。pattern space先读入1,然后执行到N,把下一行添加到当前的pattern space中,pattern space内容为(1\n2,对否?),然后执行d操作被删除。接下去读入3(系统读入总是覆盖原有内容),执行N,pattern space 内容变为(3\n4),然后再被删除。
[smallpboy @local tmp]$ seq 7 | sed ‘N;d’       #你知道它输出什么吗?
7
你猜对了吗? 简单吧? 

        -n 参数指不自动打印pattern space内容,有的人对它理解不够导致测试n/N区别时被搞的越来越糊涂了。
[smallpboy @local tmp]$ seq 4 | sed –n ‘n’
[smallpboy @local tmp]$ seq 4 | sed –n ‘N’
上述两个不输出任何信息,不用说了吧! :)
[smallpboy @local tmp]$ seq 4 | sed –n ‘n;p’      
2
4
这个能理解么? 参数p指打印pattern space的内容。
[smallpboy @local tmp]$ seq 4 | sed –n ‘N;p’
1
2
3
4
这个呢?也懂!对吧。
[smallpboy @local tmp]$ seq 5 | sed –n ‘N;p’
1
2
3
4
这个呢?也懂吧?再看看这个
[smallpboy @local tmp]$ seq 5 | sed –n ‘n;p’
自己实验去。:)自己动手才记得牢。

•接下说x
sed有hold space和pattern space,x的意思就是将hold space和pattern space的内容交换。咱实验下,看懂上面n/N区别的你,看懂下面的实验就很轻松了。
[smallpboy @local tmp]$ seq 4 | sed –n ‘x;p’

1
2
3
第一行空白?没错,因为pattern space读入1时,hold space还是空的,两者一交换,pattern space不就成空了吗?而hold space持有1,对否?然后,hold space 和 pattern space再交换内容,此时pattern space得到1,hold space得到2,打印pattern space不就打印出1了。
序列最后是4,但只能打印出3,也能理解了吧。因为4在hold space里了。
        在sedline中有一题:在每个含有字符串regex的行上插入一行空白行。
[smallpboy @local tmp]$ seq 4 | sed ‘/3/{x;p;x;}’
1
2

3
4
看懂了没?在找到regex的那一行时,pattern space的内容不就是这匹配的整行数据么,跟hold space交换后,pattern space不就为空了,然后执行p操作输出空行,然后再跟hold space交换内容,这时pattern space不就又拿到其原本的数据了吗?你有可能会问,括号里为什么要有p操作啊,命令啥时自动输出pattern space内容啊?额,这个你可是试试把p去掉后结果是怎么样的啊,看下结果你就懂啦。或者是你看如下操作
[smallpboy @local tmp]$ seq 4 | sed ‘/3/{x;p;x;d}’
1
2

4
我们的操作都是括号里面,所以输出删除等操作由你自己决定啦。这样解释x操作能懂了吧?

•接下去讲h/H,分别为复制(覆盖)/添加pattern space到hold space。
这个没什么例子能单独举的呢。不行?必须要例子。。额。好吧,看下面。
[smallpboy @local tmp]$ seq 4 | sed ‘x’       #还记得结果吗?跟sed –n ‘x;p’一样的哦。

1
2
3
[smallpboy @local tmp]$ seq 4 | sed ‘h;x’
1
2
3
4
很容易懂吧?h操作把pattern space内容复制到hold space去了。x操作交换它俩的内容,两者一模一样,交换个啥啊。:)
[smallpboy @local tmp]$ seq 4 | sed ‘x;h’




额,我浪费版面?额,我哭。是输出四个空行啦。x操作把空的hold space和pattern space交换,然后空的pattern space又把它自己复制给hold space,这样hold space和pattern space永远都成空了。╮(╯▽╰)╭,解释清楚了没?

•接下去讲g/G,分别为复制(覆盖)/添加hold space到pattern space。
假如你想要把能匹配regex的这一行变成空行,可以考虑用g哦。假如你想要把能匹配regex的这一行下一行再添加一空行,可以考虑用G哦。
[smallpboy @local tmp]$ seq 4 | sed ‘/3/g’
1
2

4
原理?额,不用多说了吧。想不通?你再想想。额,很简单。我还是smallpboy啊,大鸟飞过就好了嘛。

sed其他:
1、        wc –l功能:
sed –n ‘$=’ filename     
“=”操作指打印行号,可以执行sed –n ‘=’ filename仔细体会下它和-n之间的关系。“$”指最后一行。
2、        tac 功能
sed ‘1!G;h;$!d’ filename
G和h操作还记得么?忘了就去前面看看吧。这里难懂的还有“1!”和“$!”,其实它俩很简单,在其他语言中就是“!1”和“!$”这样,即非第一行,非最后一行的意思。这块能懂吗?类似的,删除空行使用 sed ‘/^$/d’,那删除非空行呢?删除非空行?对,使用sed ‘/^$/!d’就好了嘛。好了,如果了解了“1!”和“$!”的意思了,现在可以开始分解上述命令了。
[smallpboy @local tmp]$ seq 3 | sed ‘1!;G’
1
2

3

“1”下面没有空行是否在你预料之内呢?G操作在第二行(也就是第二次操作)之后才起作用。
[smallpboy @local tmp]$ seq 3 | sed ‘1!;G;h’
这个就复杂了,h操作将pattern space内容复制到hold space,第一次读入1时,G操作被禁止,pattern space内容为1吧。然后h操作将这个1复制过去了。第二次读入2时,G操作将hold space内容添加到pattern space(结果为2\n1,能跟上我的思路不?),然后h操作将hold space的内容从第一次结束时的1,更新为2\n1,也就是第二次结束的结果。这样,当读入3时(也即是第三次),G操作将pattern space变成了3\n2\n1。是否?:)所以上述命令输出如下:
1
2\n1
3\n2\n1
能看懂么?当然,终端上可不会显示“\n”字符的哈。最后,指保留最后一行,大功告成:
[smallpboy @local tmp]$ seq 3 | sed ‘1!;G;h;$!d’
3
2
1
这样,全懂了吧? ╮(╯▽╰)╭,说的好纠结,好婆妈啊。^)^

3、        rev功能
sed ‘/\n/!G;s/\(.\)\(.*\n\)/&\2\1;//D;s/.//;’
实话说,这个命令确实,我也半懂不懂的,确实很复杂啊。勉强说下:
“/\n/!G;”这个能理解不?在stdin中没有找到\n,就主动添上\n。
“s/\(.\)\(.*\n\)/&\2\1;”中\(.\)先匹配一个字符,再匹配剩下所有字符。“&”指整个pattern space,\2和\1想必你也知道是什么东东。
“//D”指删除pattern space第一行,space非空就循环执行。“s/.//”就不解释了。假设我们有文件:
[smallpboy @local tmp]$ cat file
123
file文件中“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….,发现匹配不了,此时pattern space没有被重新赋值。执行//D操作后,结果为321。然后,然后,就发现错了。。。。。
[smallpboy @local tmp]$ cat file | sed ‘/\n/!G;s/\(.\)\(.*\n\)/&\2\1;P;//D’  
123
23
3

321
#P print up to the first embedded newline of the current pattern space。
[smallpboy @local tmp]$ cat file | sed ‘/\n/!G;s/\(.\)\(.*\n\)/&\2\1;//D’

321
最后一步根本没有执行//D操作,或是执行//D没有删除“\n321”前面这个“\n”?D的解释是delete up to the first embedded newline of the current pattern space。额,这个D是只能删除 新的pattern space 的第一行吗? 小弟我也没有明白,还请大牛们解释下了,文章也只能写到这里了。

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

论坛徽章:
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-06 16:07 |只看该作者
这是LZ的转贴?

论坛徽章:
0
4 [报告]
发表于 2012-08-06 17:15 |只看该作者
不得不佩服。看过楼主的这贴。让我恍然醒悟,原来如此,原来如此!
非常谢谢楼主的分享!!!

论坛徽章:
0
5 [报告]
发表于 2012-08-06 17:33 |只看该作者
楼主讲的很浅显易懂啊!感谢楼主分享

论坛徽章:
0
6 [报告]
发表于 2012-08-07 13:02 |只看该作者
楼主自创的神贴。  

回复 3# blackold


   

论坛徽章:
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
7 [报告]
发表于 2012-08-07 13:03 |只看该作者
回复 6# smallpboy


    支持!!恭喜!!

论坛徽章:
0
8 [报告]
发表于 2012-08-07 13:14 |只看该作者
嘿嘿,我是新手。现在正在学shell,所以热情比较高涨。black哥,你是这里的常客高手了,以后不懂的问题还要你多多解答了。

回复 7# blackold


   

论坛徽章:
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
9 [报告]
发表于 2012-08-07 13:21 |只看该作者
回复 8# smallpboy


    相互学习而已,无所谓高手不高手。

论坛徽章:
16
IT运维版块每日发帖之星
日期:2015-08-24 06:20:00综合交流区版块每日发帖之星
日期:2015-10-14 06:20:00IT运维版块每日发帖之星
日期:2015-10-25 06:20:00IT运维版块每日发帖之星
日期:2015-11-06 06:20:00IT运维版块每日发帖之星
日期:2015-12-10 06:20:00平安夜徽章
日期:2015-12-26 00:06:302016猴年福章徽章
日期:2016-02-18 15:30:34IT运维版块每日发帖之星
日期:2016-04-15 06:20:00IT运维版块每日发帖之星
日期:2016-05-21 06:20:00综合交流区版块每日发帖之星
日期:2016-08-16 06:20:002015七夕节徽章
日期:2015-08-21 11:06:17IT运维版块每日发帖之星
日期:2015-08-14 06:20:00
10 [报告]
发表于 2012-08-07 15:32 |只看该作者
黑哥热心谦虚啊
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP