regex - grep 替换子字符串时出现意外行为

标签 regex replace grep substring oh-my-zsh

我在理解如何使用 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}是任意字母。

灵感来自https://stackoverflow.com/a/6995010/6632736 .

关于regex - grep 替换子字符串时出现意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64075904/

相关文章:

javascript - jQuery:追加到文本区域内段落的 html 的最佳方式

python - 子进程 - Grep Broken Pipe

regex - sed 版本提取

Python 正则表达式在模式中出现零次或多次

perl - vim:交互式搜索并替换为与 perl 兼容的正则表达式

正则表达式 $1 变量重置

java - 替换一个字符串。

python - 如何打印包含某些特定模式的程序的完整功能摘录

java - 如何用单个子字符串替换连续出现的子字符串?

python - 将 Regex 与 Python 结合使用来获取 iframe src 的特定部分