做为sed初学者,下面几个命令理解起来有点儿困难,我自己也是在慢慢摸索当中,把我在学习过程当中总结的一些东东和大学分享下,如果有不正确的地方欢迎指正。

【D】
D表示清除模式空间中的从模式头到第一个\n之间的内容(可以简单的理解为清除模式空间中第一行),如果清除后模式空间仍有剩余行,则执行D之前的命令(如之前有多个命令需依次执行),再执行D命令,如此循环直到不能往模式空间中追加新行为止。
注意D有循环的意思在里面
 
【d】
d比较容易理解,就是清除模式空间所有行
 
比较:
如果模式空间只有一行,D与d一样;
如果模式空间有多行,D会循环执行D之前的命令对模式空间中的行进行处理。而d则会清除模式空间行,读入新行。
 
【P】
打印模式空间中从模式头到第一个\n之间的内容(可以简单的理解为打印模式空间中第一行)。
 
【p】
模式空间中的内容全部打印出来
 
比较:
如果模式空间只有一行,P与p一样;
如果模式空间有多行,P只打印模式空间中第一行,p则会全部打印;
 
【N】
追加下一个输入行到到模板块后并在二者间嵌入新行,改变当前行号码。如果没有下一个可处理的行则退出。
 
【n】
读取下一个输入行,用下一个命令处理新行,而不是用第一个命令。
 
区别:
N是向模式空间追加下一行,而不会覆盖掉模式空间已有行;
n在读入下一行时,会产生几个操作,将模式空间已有行输出,读取下一行到模式空间,执行下一个命名。
 
为了方便理解sed执行过程,可以安装一下名为sedsed的调试工具,放在附件里供下载
看几个有趣的例子
创建一个名为eee的文件,内容如下

获取文件最后一行
 

以上两种方式都可以实现同样的需求,但执行过程确完全不一样,我们用sedsed调试工具看下

PATT:表示模式空间
COMM:执行的命令
HOLD:表示保持空间 (命令隐藏了保持空间的内容,因为没有用到,保持空间为空)
 
从命令执行过程可以看出在执行[sed ‘$!D’]命令时,sed每次往模式空间读入一行,命令“$!D”便判断是否为最后一行,如果不是则删除模式空间这唯一的一行,接着sed再读入下一行,如此直到sed往模式空间输入最后一行,命令“$!D”判读后不删除,最后模式空间就剩下最后一行,输出到屏幕。
 
接着看下一个命令执行过程

N是个很有意思的命令,它会向模式空间追加入新行,看到的效果形如“1111\n2222$”
命令[‘N;D’]可以说将N与D的特点很好的表现出来了,sed首先向模式空间读入第一行“1111$”,然后执行N命令,追加第二行,模式空间变为“1111\n2222$”,然后执行D命令,我们知道D命令是删除模式空间中的第一行,而现在模式空间有二行,删除后模式空间变为“2222$”,模式空间有剩余行,就会执行D循环,执行D之前的命令,接着执行N命令,追加下一行,模式空间就成了“2222\n3333$”,接着执行D。如此循环,直到N没有可加入的行时则退出,模式空间就剩最后一行,在屏幕上打印出来。
再看一个稍复杂一点儿的,删除文本中最后两行

看下命令执行过程

sed读入第1行,执行N命令追加第2行,执行P命令打印模式空间中第1行(1111$),执行D命令删除模式空间第1行,现在模式空间中还有第2行,则执行D循环,执行D之前命令,又执行N命令追加第3行,执行P命令打印模式空间第1行(2222$),执行D命令,删除模式空间第1行,如此类推,直到N追加最后一行后,模式空间存在最后2行(3333\n4444$),P命令判断后不执行,D命令判断后不执行,但d命令判断后执行,d会清除模式空间所有行,OK,最后2行就这么没有了。
接着再看一个例子,显示文本中的奇数行

命令执行过程如下

这里要需要注意的地方,这里加了“n”这个选项,目的是打断sed默认输出,将输出的控制权交给命令。sed向模式空间读入新行时,是覆盖式读入。
用下面的命令也可以取得相同的效果

命令执行过程如下:

n这个命令是读取模式空间中当前行的下一行,sed往模式空间读入第1行(1111$),执行n命令,模式空间中的第1行会输出到屏幕,模式空间读入第2行(2222$),d会删除这行,接着sed读入第3,执行n命令,第3行输入到屏幕,模式空间读入第4行(4444$),执行d命令删除第4行,最终结果是屏幕输出了奇数行。这里需要注意的是,执行n命令时会发生两个操作,第一个操作是将当前模式空间内容输出到屏幕(这是sed的默认输出),第二个操作是覆盖式读入下一行到模式空间。
如果理解了上面的例子,再看下如何读取文本中的偶数行

是不是和上面的例子很像,这里区别就是添加了“n”选项,打断默认输出,然后用p取代d,也就是直接打印模式空间中偶数行
看下执行过程