首页 > 解决方案 > 使用 Vim 的正则表达式替换多个文件的单词在 sed 中无法按预期工作

问题描述

我正在尝试使用正则表达式替换包含代码的许多文件的单词。我不太了解正则表达式,但我可以通过以下命令使用 Vim 在一个文件中获得所需的效果:

:%s/\<Cat\>/Dog/g

(Cat, Cats) Cat,somethingelse, Cat.blah因此,例如,在 Vim 中使用 this 将替代,例如

(Dog, Cats) Dog,somethingelse, Dog.blah

这正是我想要的!

但是,如果我使用相同的正则表达式sed(我认为最终我需要用它来替换许多文件),我会得到例如:

$ line="(Cat, Cats) Cat,somethingelse, Cat.blah"
$ echo "$line" | sed -n "s/\<Cat\>/Dog/p"
(Dog, Cats) Cat,somethingelse, Cat.blah

这是错误的输出!

所以我的主要问题是:如何在 Vim 之外获得我想要的效果。(第二个问题是:为什么这些行为首先不同?)

标签: vimsed

解决方案


你有错误的修饰符sed来达到预期的效果。-n和在这种/p情况下并不完全正确。你应该用过

sed 's/\<Cat\>/Dog/g'

实现相当于Vim的:%s/\<Cat\>/Dog/g命令。

修饰符具有替换所有匹配字段的/g效果,即用替换字符串替换多次出现的源字符串。和标志用于条件打印逻辑,即如果找到模式则打印该-n行。/psedCat

另请注意,您仍然可以使用-nand /pwith /g。但是一个关键的区别是,如果源字符串不存在,则不会将任何内容打印到标准输出。但是没有它就不会发生同样的事情,你只会看到一个未修改的字符串被打印出来。

echo "$line" | sed 's/\<foo\>/Dog/g'
(Cat, Cats) Cat,somethingelse, Cat.blah

及以下不产生任何输出

echo "$line" | sed -n 's/\<foo\>/Dog/gp'

推荐阅读