免费注册 查看新帖 |

Chinaunix

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

[学习共享] sed N P D 彻底讲解 [复制链接]

论坛徽章:
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
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2019-02-02 10:31 |只看该作者 |倒序浏览
本帖最后由 expert1 于 2019-02-13 16:20 编辑

N年前研究过这个,忘了做笔记,真是好记性不如烂笔头。 最近又遇到而且想起了这个问题。简单分享和探讨下,如果有不对之处,欢迎批评指正。
注意,以下需要对sed的工作模式,包括pattern space有一定的理解。

1. N

Add a newline to the pattern space, then append the next line of input to the pattern space. If there is no more input then sed exits without processing any more commands.


简单说,N加一个\n, 然后追加下一行到当前的pattern space, 如果没有下一行,退出。 这也隐含了一个事实: N会改变input的行号
---------------


       P      Print up to the first embedded newline of the current pattern space.

P 打印pattern 第一个\n(包括\n)的内容。

------


一个例子:
  1. seq 5 | sed -n 'N;P'
复制代码
1
3

debug一下pattern space,可见N改变了输入行号。
  1. seq 5 |sed -n 'l;N;P'
复制代码



分析,读入1,N追加,此时pattern space是1\n2,P打印1\n,输出1, 注意此时input变成了3(也就是到了第三行。如果没有N,此时应该是第2行。),然后是3\n4,打印3。此时Input是5,由于 no more input, 此时退出,后面的P也不执行了。虽然此时pattern space是5,但由于 -n 抑制了自动打印。所以最终结果是
1
3
# 可见N在没有input的时候,会自动退出sed 工作流程,之后的都不再执行了。

----------------------------------------------------

下面再说一下最不容易理解的D


D
If pattern space contains no newline, start a normal new cycle as if the d command was issued. Otherwise, delete text in the pattern space up to the first newline, and restart cycle with the resultant pattern space, without reading a new line of input.
从解释看,D在pattern space没有\n(只有用了N,才有\n,除非你特殊替换等)的情况下,和d一样都是删掉pattern space的内容,然后跳到命令的开头(这里的跳到开头在下面解释),并且读入下一行再处理(正常的工作cycle就是这样)。

Otherwise,也就是pattern space有内容(大多数情况下是用了N),把pattern space的第一个\n之前的内容删掉,然后继续跳到开头循环,不读入下一行。

  1. seq 9 | sed 'N;D;P'
复制代码
9

1读入2,pattern space是1\n2, contains newline了,D删掉1\n, 然后继续跳到开头(构成了循环),也就是最开始的地方, 继续N,此时pattern space是2\n3, 删掉2\n, 以此类推。最后8\n9,删掉8\n, pattern space是9,由于N 不满足(没有内容可以输入了),退出。可见,D后面的P完全不起作用,D构成了一个循环。

结果9 是由于pattern space是9, 又没有-n 抑制自动打印pattern space,所以得到的9

without reading a new line of input, 这个做什么的呢? 比如说1\n2,按照正常情况下,下一个Input应该是3了(
  1. sed -n 'N;P;D'
复制代码

), 但D不再读取input了,直接跳到开头,所以必须有N来负责读入下一行,此时pattern space的内容是2, 就着这个pattern space,跳到命令的开头,也就是N,这样就是2\n3了,可以对比一下,有D和无D的时候,pattern space的内容一看就知道了。


------------------------------------------------
另外一个例子,可以清晰的看到D,如果没有N,而pattern space又有内容的话,下一行永远不会被处理。
  1. seq 5 | sed 's/^/hello\n/;p; D'
复制代码

这个是个无限的循环,第一次,hello\n1, 然后p打印,D删掉hello\n, 然后循环,再替换,再打印,再D。就是2永远没有机会处理。


综合以上,我们发现,D多数情况情况下,必须跟在N后面,不然的话下一行是不会读入的,成了循环。而P,必须在D前面,不然没机会P(D构成了循环,直到pattern space没东西,才轮到P)。

他们的顺序是 N P D

也就是N追加,P打印需要的,D删掉,继续循环(由D构成的循环,也就是restart  cycle)。

最后,一个例子来学习一下,假设以下是学习成绩,要变成
tom 99 ..
jerry ...

  1. 那么 sed ':a;N;/\n[A-Za-z]/!s/\n/ /;ta;P;D'
复制代码

# file
tom
99
86
92
jerry
96
87

----------
最后 对比,加了D,由于每次循环到N,等于是逐行处理了。
  1. seq 5 |sed -n 'l;N;P;D'
  2. 1$
  3. 1
  4. 2$
  5. 2
  6. 3$
  7. 3
  8. 4$
  9. 4
  10. 5$
复制代码





论坛徽章:
93
2015年辞旧岁徽章
日期:2019-10-10 10:51:15CU大牛徽章
日期:2014-02-21 14:21:56CU十二周年纪念徽章
日期:2020-10-15 16:55:55CU大牛徽章
日期:2014-02-21 14:22:07羊年新春福章
日期:2019-10-10 10:51:39CU大牛徽章
日期:2019-10-10 10:55:38季节之章:春
日期:2020-10-15 16:57:40ChinaUnix元老
日期:2019-10-10 10:54:42季节之章:冬
日期:2019-10-10 10:57:17CU大牛徽章
日期:2014-02-21 14:22:52CU大牛徽章
日期:2014-03-13 10:40:30CU大牛徽章
日期:2014-02-21 14:23:15
2 [报告]
发表于 2019-02-02 10:59 |只看该作者
大过年的还在更新,赶紧来顶顶。

论坛徽章:
10
15-16赛季CBA联赛之同曦
日期:2016-06-11 19:22:4115-16赛季CBA联赛之深圳
日期:2020-05-31 16:13:5615-16赛季CBA联赛之同曦
日期:2020-01-28 12:42:47每日论坛发贴之星
日期:2016-08-09 06:20:00程序设计版块每日发帖之星
日期:2016-08-09 06:20:00每日论坛发贴之星
日期:2016-07-12 06:20:00程序设计版块每日发帖之星
日期:2016-07-12 06:20:00程序设计版块每日发帖之星
日期:2016-07-06 06:20:00程序设计版块每日发帖之星
日期:2016-07-04 06:20:0015-16赛季CBA联赛之佛山
日期:2021-02-26 09:33:41
3 [报告]
发表于 2019-02-02 11:05 |只看该作者
好贴要顶= =,好久不用sed了

论坛徽章:
8
摩羯座
日期:2014-11-26 18:59:452015亚冠之浦和红钻
日期:2015-06-23 19:10:532015亚冠之西悉尼流浪者
日期:2015-08-21 08:40:5815-16赛季CBA联赛之山东
日期:2016-01-31 18:25:0515-16赛季CBA联赛之四川
日期:2016-02-16 16:08:30程序设计版块每日发帖之星
日期:2016-06-29 06:20:002017金鸡报晓
日期:2017-01-10 15:19:5615-16赛季CBA联赛之佛山
日期:2017-02-27 20:41:19
4 [报告]
发表于 2019-02-04 15:01 |只看该作者
牛!学习了!

论坛徽章:
0
5 [报告]
发表于 2019-02-10 15:50 来自手机 |只看该作者
好像是什么空间模式。。

论坛徽章:
0
6 [报告]
发表于 2019-02-10 15:50 来自手机 |只看该作者
好像是什么空间模式。。

论坛徽章:
3
2015年迎新春徽章
日期:2015-03-04 09:56:11数据库技术版块每日发帖之星
日期:2016-08-03 06:20:00数据库技术版块每日发帖之星
日期:2016-08-04 06:20:00
7 [报告]
发表于 2019-02-11 15:25 |只看该作者
本帖最后由 cjaizss 于 2019-02-13 12:37 编辑

套神威武Spirit Tom Tall Big Up, b/c he is the No. 1 spirit w/o any explaination.
向套神致敬!


论坛徽章:
2
射手座
日期:2014-10-10 15:59:4715-16赛季CBA联赛之上海
日期:2016-03-03 10:27:14
8 [报告]
发表于 2019-02-13 11:40 |只看该作者
母神v5,牛,学习了!

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

论坛徽章:
1
巳蛇
日期:2013-10-28 15:55:33
10 [报告]
发表于 2019-02-13 11:49 |只看该作者
专程绑定手机号登陆膜拜!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP