sed'$!N; $!D'解释

时间:2011-01-27 13:19:56

标签: unix string sed

我知道

cat foo | sed '$!N;$!D'

将打印出文件 foo 的最后两行,但我不明白为什么。

我已经阅读了手册页并且知道N加入了当前处理线的下一行等等 - 但是有人可以用“良好的英语”来解释这里的操作顺序是一步一步的吗?

谢谢!

2 个答案:

答案 0 :(得分:4)

这是通过sedsed调试器运行时脚本的样子(Aurelio Jargas):

$ echo -e 'a\nb\nc\nd' | sed '$!N;$!D'        PATT:^a$
PATT:^a$
COMM:$ !N
PATT:^a\Nb$
COMM:$ !D
PATT:^b$
COMM:$ !N
PATT:^b\Nc$
COMM:$ !D
PATT:^c$
COMM:$ !N
PATT:^c\Nd$
COMM:$ !D
PATT:^c\Nd$
c
d

我已经过滤掉了显示保留空间(“HOLD”)的行,因为它没有被使用。 “PATT”显示模式空间中的内容,“COMM”显示即将执行的命令。 “\ N”表示嵌入的换行符。当然,“^”和“$”表示字符串的开头和结尾。

!N附加下一行,!D删除前一行并循环到脚本的开头而不进行隐式打印。当读取最后一行时,$!测试失败,因此没有什么可做的,脚本退出并执行模式空间中剩余内容的隐式打印(因为参数中未指定-n )。

免责声明:我是sedsed项目的贡献者,并做了一些小改进,包括扩展色彩支持,添加^行开头指标和Python 3的初步支持。版本(最近没有被触及)是here

答案 1 :(得分:1)

$!N;$!D是一个sed计划,由两个语句$!N$!D组成。

$!N匹配输入的最后一行文件的最后一行($!否定)并在其上运行N命令,正如您所说你自己将下一行输入附加到当前正在审查的行(“模式空间”)。换句话说,sed现在在模式空间中有两行,并且已经前进到下一行。

$!D也匹配除最后一行之外的所有内容,并将模式空间擦除到第一个换行符。 D还会阻止sed在读取下一行时擦除整个模式空间。

因此,正在执行的算法大致是:

For every line up to but not including the last {
    Read the next line and append it to the pattern space
    If still not at the last line
        Delete the first line in the pattern space
}
Print the pattern space