SED代码说明

时间:2014-09-05 20:47:31

标签: sed

我在下面有一行SED,这是我每月运行的批处理命令。它是由我之前的某人编写的,我希望了解此代码的各个部分。从两个输出中我可以看出,当顺序行重复时,它需要一行并删除另一行,我只是不明白它是如何用这一行完成的。

sed "$!N; /^\(.*\)\n\1$/!P; D" finalish.txt > final.txt

- Finalish.txt

的例子
201408
201409
201409
201409
201409

示例 - Final.txt

201408
201409

2 个答案:

答案 0 :(得分:2)

不进入sed的基础知识,这是您的sed命令已经细分:

  • $!N:如果它不是文件结尾,请将下一行追加到模式空间。这两行将用换行符分隔(\n)。此时您的模式空间为201408\n201409
  • /^\(.*\)\n\1$/!P:如果模式空间包含由换行符\n)分隔的两个相似内容,那么P会转到第一个换行符(\n)。所以这会将201408打印到STDOUT。但是在第二次迭代期间,模式空间将具有201409\n201409,并且由于失败正则表达式,所以没有任何内容被打印,我们继续执行下一个命令。
  • DD选择第一个换行符(\n)并重复sed脚本。请记住,在重复循环期间,您的模式空间仍然具有201409

因此,在第一次迭代中,201408被打印但201409在到达文件末尾之前不会被打印,这时你的正则表达式将再次变为真,并且内容将被打印。

如果您继承了很多sed代码,我强烈推荐使用python编写的sedsed实用程序,它将帮助您理解错综复杂的sed经常成为维护的噩梦。

以下是从sedsed实用程序运行的示例(我没有显示所有迭代,因为它非常详细,但是你得到了图片。我对输出的真正意义添加了一些注释。另请注意我我使用单引号,因为我在Mac(BSD Unix)而不是Windows):

$ sedsed.py -d '$!N; /^\(.*\)\n\1$/!P; D' file
PATT:201408$           # This shows your current pattern space
HOLD:$                 # This shows your current hold buffer
COMM:$ !N              # This shows the command that is going to run
PATT:201408$           # This shows the pattern space after the command has ran
201409$           
HOLD:$                 # This shows the hold buffer after the command has ran
COMM:/^\(.*\)\n\1$/ !P # This shows the command being ran
201408                 # Anything without a <TAG:> is what gets printed to STDOUT
PATT:201408$
201409$
HOLD:$
COMM:D
PATT:201409$
HOLD:$
...
...
...
COMM:$ !N
PATT:201409$
HOLD:$
COMM:/^\(.*\)\n\1$/ !P
201409
PATT:201409$
HOLD:$
COMM:D

我还建议,一旦您了解了sed命令的编写内容,就可以将它们移植到更友好的脚本语言,如awkperl或{{ 1}}

答案 1 :(得分:0)

这不会帮助您理解sed,但这里只有awk才能获得唯一的行。

awk '!seen[$0]++' finalish.txt
201408
201409