我正在使用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
语句。
答案 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的东西。