sed替代品并显示行号

时间:2014-07-26 00:05:19

标签: bash awk sed

我正在使用bash尝试在文件上使用sed替换,并显示替换发生的行号和行的最终版本。对于包含foo的行的文件,请尝试使用

sed -n 's/foo/bar/gp' filename

将显示替换发生的行,但我无法弄清楚如何包含行号。如果我尝试使用=作为标记来打印当前行号,如

sed -n 's/foo/bar/gp=' filename

我得到了

sed: -e expression #1, char 14: unknown option to `s'

我可以使用awk

来完成目标
 awk '{if (sub("foo","bar",$0)){print NR $0}}' filename

但我很好奇是否有办法用一行sed执行此操作。如果可能的话,我很乐意在没有管道的情况下使用单个sed语句。

2 个答案:

答案 0 :(得分:4)

在没有列出搜索模式两次并使用command grouping的情况下,我无法想办法。

sed -n "/foo/{s/foo/bar/g;=;p;}" filename

编辑mklement0通过提及如果模式空间为空来帮助我,那么默认模式空间是最后使用的模式空间,如上所述in the manual。所以你可以像这样逃避:

sed -n "/foo/{s//bar/g;=;p;}" filename

在此之前,我想出了一种不重复模式空间的方法,但它使用了分支和标签。 "在大多数情况下,"文档指定,"使用这些命令表明你可能更喜欢用awk或Perl这样的编程。但偶尔会有人坚持使用sed,而这些命令可以让人们编写非常复杂的脚本。" [source]

sed -n "s/foo/bar/g;tp;b;:p;=;p" filename

执行以下操作:

  • s/foo/bar/g替换。
  • 如果发生替换,
  • tp将跳转至:p
  • b(没有标签的分支)将处理下一行。
  • :p定义标签p,这是上面tp命令的目标。
  • =p会打印行号,然后是行。
  • 脚本结束,请返回并处理下一行。

请参阅?更不可读......也许是:(){ :|:& };:的远房表亲。 :)

答案 1 :(得分:1)

使用sed无法以任何合理的方式完成,这里是如何在awk中清楚简单地做到这一点:

awk 'sub(/foo/,"bar"){print NR, $0}' filename

sed是一个很好的工具,可以在一行上进行简单的替换,对于其他任何使用awk的东西。