[精彩] 请问sed的P命令和D命令的用法

950阅读 0评论2010-03-10 greendays
分类:

sed大写的P命令和D命令的用法我不明白。看了man,上面写:
D   Deletes the initial segment of the pattern space through the first  newline and starts the next cycle.
P   Prints (copies) the initial segment of the pattern space through the  first newline to the standard output.
但是里面那句through the first  newline 看不懂,是什么意思?newline指的是什么?还有initial segment 指的又是什么?谁能结合一些例子讲解一下?



  回复于:2004-03-18 17:30:32

这帖子沉到底了。顶上来。
请sed达人就以下例子为我解释一下:
引用:
6.按关键字拼接行 
如果某行以=开始,则合并到上一行并替代=为空格 

代码: 
sed -e :a -e '$!N;s/\n=/ /;ta' -e 'P;D' 

举例 
代码: 
cat file 
111111111111111111 
222222222222222222 
=333333333333333333 
444444444444444444 

sed -e :a -e '$!N;s/\n=/ /;ta' -e 'P;D' filename 
111111111111111111 
222222222222222222 333333333333333333 
444444444444444444 


如果不加-e'P;D',那么后面的以“=”号开头的行都不会合并上来,可是我不理解-e'P;D'的意思,请高手解释一下。


  回复于:2004-03-18 17:40:36

见ad版主的sed学习日记:



  回复于:2004-03-18 18:11:21

我这个例子就是从那篇帖子里面抄的呀,但是这个例子还是没有看懂。能不能结合这个例子解释一下?


  回复于:2004-03-18 18:55:09

我来试着解释一下,如有不妥,请见谅。
-e :a 定义一个标签位置
$!N   如果不是最后一行,就读入新行附加于pattern space之后,以“\n”分隔
s/\n=/ /  如果发现了新行是以=开头的,替换为空格
ta      如果找到了替换,从标签a处再执行,否则向下走
P     打印 pattern space中的第一个 \n之前的内容
D     删除pattern space中的第一个 \n之前的内容,并返回脚本头部执行
各个命令解释清楚了,再看执行过程:
第一行执行,没有找到 \n= 打印第一行,读入第二行,脚本头部执行
第二行执行,找到 \n= ,替换为空格,从标签a处再执行
第三行执行,没有找到 \n= 打印第二三行的合并和第四行,读入新行,没有了,结束。



 我非常敬仰admirer,如有不对,请指正。


  回复于:2004-03-19 09:52:54

引用:
-e :a 定义一个标签位置


理解

引用:
$!N 如果不是最后一行,就读入新行附加于pattern space之后,以“\n”分隔


理解

引用:
s/\n=/ / 如果发现了新行是以=开头的,替换为空格


理解

引用:
ta 如果找到了替换,从标签a处再执行,否则向下走


不理解,这条命令有分条件执行吗?为什么说“如果找到替换再到a执行”,s命令后不是都要执行ta这条命令吗,哪个命令指定这条ta是根据s的结果来处理的?

引用:
P 打印 pattern space中的第一个 \n之前的内容 
D 删除pattern space中的第一个 \n之前的内容,并返回脚本头部执行 


理解


引用:
第一行执行,没有找到 \n= 打印第一行,读入第二行,脚本头部执行


是不是先定义标号a,然后N读入下一行,然后执行s替换,因为没有找到替换,所以不执行ta?然后打印模式空间中\n前面内容,就是第一行,再删除模式空间\n前面内容即第一行,保留第二行。
引用:
第二行执行,找到 \n= ,替换为空格,从标签a处再执行 
第三行执行,没有找到 \n= 打印第二三行的合并和第四行,读入新行,没有了,结束。


此时模式空间里面是第二行。先定义标号a,然后N读入下一行(第三行),然后执行s替换,这时\n就没有了,模式空间是2、3行的合并,然后ta,再N读入下一行(第四行),然后执行s替换,因为没有找到替换,所以不执行ta,然后打印模式空间中\n前面内容,就是二、三行的合并,删除后保留第四行。
这时再执行sed,定义标号a,发现是最后一行,所以N,s,t三个命令都不执行,执行P;D命令,打印第四行,再删除模式空间的内容。


我的理解对吗?
问题:N命令是由前面的$!决定是否执行的,这个我理解。s命令的执行条件是什么?是不是前面的N执行成功s才执行?t命令的执行条件是不是s命令成功才执行?-e :a和-e'P;D'是不是不管什么条件都执行?
请大虾赐教!


  回复于:2004-03-19 10:24:09

我的第三行执行写的不清楚,图了省事,你的理解很不错,但也有点问题。
    就是这个 -e:a有点问题,我不知道自己理解的是否对,我认为这个标签只定义一次。不是每一行都定义的。还有这个ta 他就相当于if found 替换 goto a;
      s命令的执行无条件,有就替换,没有就不替换;'P;D'是不管什么条件都执行。
    欢迎交流。


  回复于:2004-03-19 10:46:34

我是觉得sed的每一个命令地位都是相等的,所以我认为-e :a是每读入一行的时候都执行一次。
还有如果s命令没有条件的话,那么t命令为什么就是“if found 替换”才能跳到a呢?s命令为什么不是“if found 替换”再执行替换呢?我觉得s命令和t命令的执行顺序是按顺序执行的,所以如果s命令有执行,t命令也要执行。如果s命令没有执行(当然不考虑s匹配不到自己的正则表达式的情况),那么t命令也不会执行。对吗?
我现在P命令和D命令已经搞明白了,但是命令组合中的命令执行顺序和执行条件越搞越不明白。比如下列几种情况:
sed -e 'comd1' -e 'comd2'
sed -e 'comd1;comd2'
sed -e '$!comd1;comd2'
sed -e '/reg/{comd1;comd2;}'
不知道还有没有其他组合,这几个有什么不同吗?


  回复于:2004-03-19 11:46:47

COMM:代表命令,PATT:代表pattern space的内容,其他为sed输出的内容
PATT:111111111111111111$

COMM:: a
COMM:$ !N
PATT:111111111111111111\n222222222222222222$
COMM:s/\n=/ /
PATT:111111111111111111\n222222222222222222$
COMM:t a
COMM:P
111111111111111111
PATT:111111111111111111\n222222222222222222$
COMM:D
PATT:222222222222222222$
COMM:: a
COMM:$ !N
PATT:222222222222222222\n=333333333333333333$
COMM:s/\n=/ /
PATT:222222222222222222 333333333333333333$
COMM:t a
COMM:$ !N
PATT:222222222222222222 333333333333333333\n444444444444444444 $
COMM:s/\n=/ /
PATT:222222222222222222 333333333333333333\n444444444444444444 $
COMM:t a
COMM:P
222222222222222222 333333333333333333
PATT:222222222222222222 333333333333333333\n444444444444444444 $
COMM:D
PATT:444444444444444444 $
COMM:: a
COMM:$ !N
PATT:444444444444444444 $
COMM:s/\n=/ /
PATT:444444444444444444 $
COMM:t a
COMM:P
444444444444444444 
PATT:444444444444444444 $
COMM:D



  回复于:2004-03-19 15:23:52

看了版主的解释,应该“:a”命令和“ta”命令都是每次读入一行后都要执行的,我的理解对吗?那么仍然有一个疑问:执行了命令t a以后,为什么有时候是执行P命令,有时候是执行$!N命令?这个跳转命令的条件是什么呢?


  回复于:2004-03-19 15:26:16

请参考一下
 t label

              If  a  s///  has  done  a successful substitution since the last
              input line was read and since the last  t  or  T  command,  then
              branch to label; if label is omitted, branch to end of script.



  回复于:2004-03-19 16:03:39

看上面这段英文解释,t命令在读入一行或者上次t命令后如果有个s命令执行成功,那么t命令就跳转,否则不跳转,这个解释和我系统上面的man基本一样。
用这个解释来说明版主上面的流程,我想我是懂了。但是我自己设计了一个例子,运行结果又让我糊涂了,所以我可能不是真懂。
例子是这样的:

cat eee
aaaa
bbbbb
ccccc
ddd
eee
fff
gggg

运行命令

sed -e :a -e'N;s/b/1/;ta' eee
aaaa
11111
ccccc
ddd
eee
fff
gggg

运行命令

sed -e :a -e'N;s/c/1/;ta' eee
aaaa
bbbbb

后者的执行结果我无论如何没法理解。
我先说一下我对后者的理解:
读入第一行aaa,执行N读入第二行bbb,执行s替换,没有成功,不执行ta,打印模式空间,内容是aaa\nbbb
读入第三行ccc,执行N读入第四行ddd,执行s替换成功,模式空间是111\nddd,执行ta,再执行N读入第五行,模式空间是111\nddd\neee,执行s替换不成功,我认为此时ta应该不执行,结束命令打印模式空间111\nddd\neee,可是为什么没有?
然后应该读入第六行……,最后结果应该和前者一样,可是为什么打印到bbb这行就嘎然而止了?
希望版主和诸位大虾不要被我的无知和罗嗦吓跑,发扬耐心的传帮带的风格,谢谢。


  回复于:2004-03-19 16:17:01

呵呵,搂主很认真啊,这挺好的,不用怕麻烦。

你试着将你的文件改一下,改为如下:
aaa

bbbbb
cccc
ddd
eee
fff
gggg

就会发现,sed -e :a -e'N;s/c/1/;ta' file 输出的又有了。
 我就不解释了,自己思考一下吧。


  回复于:2004-03-19 16:18:48

哦,我明白了,因为我刚才在我的例子里面发现了一个问题:
sed -e :a -e'N;s/c/1/;ta' eee

在s命令里面没有指明替换第几个,所以缺省只替换了第一个,那么在N读入第四行时,
PATT=ccccc\nddd

s命令之后,
PATT=1cccc\nddd

ta命令之后,N读入第五行,
PATT=1cccc\nddd\neee

s命令之后,
PATT=11ccc\nddd\neee

所以ta命令继续跳转,再读入第六行,
PATT=11ccc\nddd\neee\nfff

s命令之后,
PATT=111cc\nddd\neee\nfff

……
……
所以文件读完后,因为s命令一直成功,t命令仍要执行,所以循环还没有结束,模式空间就不打出来了。如果把第三行少写几个“c”,或者eee文件多写几行,最后就可以打印出全部替换过的文件了。

实践+思考+他人帮助是成功掌握一门知识的不二法门哪。


  回复于:2004-03-19 16:24:35

引用:原帖由 "forest077"]看了版主的解释,应该“:a”命令和“ta”命令都是每次读入一行后都要执行的,
 发表:



请看b[label]的用法说明:

The label is optional, and if not supplied, control is transferred to the end of the script. If alabel is supplied, execution resumes at the line following the label.


  回复于:2004-03-19 16:24:50

发完帖子看到skydog兄的回帖,我想我的思考是对的了,但是skydog举的例子有一个问题,“ccc……”那一行的字符个数如果是4个仍然不能打印出来,如果改成3个或以下才能打印出下面几行的内容。


  回复于:2004-03-19 16:35:54

呵呵,我拷贝你的文件,文件末尾多了一个空行,所以4个正好能打印出来,我试了的。

另请注意我之前的关于b[label]的说明。


  回复于:2004-03-19 17:12:59

b和t命令的区别是不是前者是无条件跳转,后者是s命令成功后才跳转?
为什么要我注意b命令的说明,和我举的例子有什么关系吗?




原文链接:
转载请注明作者名及原文出处





Copyright © 2001-2006 ChinaUnix.net   All Rights Reserved

感谢所有关心和支持过ChinaUnix的朋友们

上一篇:sed中的N。。。
下一篇: sed 的 D 命令什么意思?