我在理解如何使用 grep 来完成看似简单的任务时遇到了一些困难。我想匹配出现在我拥有的许多文件中的子字符串,但我想忽略该子字符串前面带有字母或数字的情况
例如,我有一堆文件,其中包含以下行:
{ some word: ['bar-something', 'bar-somthing-else'] },
{ some text: ['bar-fab', 'bar-fab-foo', 'bar-eggs'] },
<bar-sometext>Hello World!</bar-sometext>
'bar-foobar-foo'
'bar-foo'
我想将所有 bar- 外观替换为 ket-,但前提是 bar 前面没有字母或数字,例如
'bar-foobar-foo'
应改为
'ket-foobar-foo'
但是我遇到了一些麻烦,因为 grep 命令与他们自己的规则不一致
让我解释一下:
命令:
git grep -l 'bar-' | xargs sed -i '' -e 's/bar-/ket-/g'
几乎可以工作,唯一的问题是它也会更改前面带有字母或数字的栏:
'bar-foobar-foo'
到 'ket-fooket-foo'
为了做一些测试,在进行替换之前我只用 grep 进行匹配。我期待该命令
grep -E '[^a-zA-Z0-9]ket-' a.file
成功了,但它也匹配单词 ket- 之前的任何特殊字符。例如,正在匹配
<bar-
'bar-
\bar-
(为了简单起见,我删除了其余的文本,上面突出显示为匹配的文本)而不是仅匹配 bar-。为什么要这样做?当我不排除字母或数字时,grep 不匹配这些前面的特殊字符。
如何仅替换 bar- 而不匹配其他任何内容,但同时忽略该子字符串前面有任何字母或数字的任何情况。我给出的示例的预期输出是:
{ some word: ['ket-something', 'ket-somthing-else'] },
{ some text: ['ket-fab', 'ket-fab-foo', 'ket-eggs'] },
<ket-sometext>Hello World!</ket-sometext>
'ket-foobar-foo'
'ket-foo'
顺便说一句,我使用的是 Mac,但在执行替换时遇到了麻烦,命令
git grep -l 'bar-' | xargs sed -i '' -e 's/bar-/ket-/g'
在我的 Mac 上使用 oh-my-zsh 终端运行得很好,我会很感激任何与上面的命令非常相似的答案
提前致谢
最佳答案
也许,您应该使用其他支持后向断言的工具。
perl -pi.bak -e 's/(?<![\p{L}\d])bar/test/g' file.txt
-
-p
处理,然后打印<>
一行一行, -
-i
激活就地编辑。file.txt
将使用.bak
进行备份扩展名, -
-e
意味着第一个参数是 Perl 单行代码,而不是 Perl 可执行文件, -
(?<!
是一个否定的lookbehind断言, -
\p{L}
是任意字母。
关于regex - grep 替换子字符串时出现意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64075904/