假设您有一个文本文件:
foo fnord bar
bizz foo poit
现在我想将“foo”和“bar”都替换为“narf”。
我知道我可以使用:
sed -e 's/foo/narf/g' -e 's/bar/narf/g' fileName
然而我想使用一个 OR 运算符来告诉正则表达式通过一个表达式来匹配两个针。
看了一些手册,我想管道应该适合我的需要,但我尝试过
sed -e 's/foo|bar/narf/g' -i fileName
它不起作用,甚至没有抛出错误。
我在这里做错了什么?
答案1
使用-r
扩展正则表达式语法的选项:
sed -r -e 's/foo|bar/narf/g'
否则,逃避析取,如下\|
:
sed -e 's/foo\|bar/narf/g'
答案2
有很多变体正则表达式句法。 Unix 世界中第一个具有正则表达式的工具并不具备正则表达式的全部功能,只有字符集 ([…]
和.
)、重复 ( *
) 和行锚点 (^
和$
)。基本正则表达式只有这些运算符。 Sed 是一种老式工具,使用基本的正则表达式。
许多 sed 实现都具有完整正则表达式匹配的扩展。因为字符|
代表它自己,所以您需要用于\|
交替,并且类似地\(
用于\)
分组。请注意,POSIX标准不强制要求\|
支持基本正则表达式,以及一些系统(例如开放BSD) 没有它。
某些版本的 sed 可以选择切换到扩展正则表达式,其中(…)
用于分组和|
交替。使用 GNU sed(即在 Linux 或 Cygwin 下)或忙碌盒,传递-r
选项。在自由BSD或者操作系统X,传递-E
选项。
如果你的 sed 没有交替,你可以调用awk
。它是由POSIX,但是对于这个任务来说有点冗长,而且它不支持反向引用。
awk '{gsub(/foo|bar/, "narf")}' <fileName.old >fileName.new
顺便说一句,只有 GNU 和 Busybox sed 支持文件就地替换。 awk 和其他版本的 sed 没有。看我可以让“cut”就地更改文件吗?
如果您有 Perl,它通常会以一种工具万能的方式方便地处理单行文本。 sed、awk 等中的大多数简单内容在 Perl 中并不困难,并且您可以通过学习单个(如果很复杂)工具来摆脱困境。
perl -i -pe 's/foo|bar/narf/g' fileName
答案3
您可以在 Ex 模式下使用 Vim:
ex -sc '%s/\vPA|QU/RO/g|x' file
%
选择所有行s
代替\v
开启魔法g
全局替换x
保存并关闭