是否有上下文替换的标准?

Is there a standard for context replacement?

在 vi 中,对于行

aaaj

我运行命令:

.s/a*\|j/x/g

线转

xj

而不是预期的

xx

这是 vi 的错误吗? sed、gawk 和 nawk 的行为符合预期,例如:

% echo aaaj | awk '{gsub(/a*|j/,"x");print}'
xx

此外,如果我 运行 命令

而不是上面的命令

.s/j\|a*/x/g

("j" 和 "a*" 交换),那么该行将按预期变为 "xx"。

这里的"problem"是第一个分支的a*子模式可以匹配空字符串

当引擎找到 aaa 时,a* 替代分支匹配三个 a,并且 substitute 将它们全部替换为 x。然后,引擎在 3 as + 1(参见 source code comments)的位置再次尝试匹配。

请注意,a* 总是匹配,"wins",而 j 永远不会匹配。发生这种情况是因为优先顺序,第一个分支总是在 Vim 正则表达式中获胜。如果您替换 aaaj jjj 它将变成 xjx xjxjxj 因为该模式将匹配不匹配字符之前的每个位置。

正确的模式

用正则表达式替换时,您通常不想匹配与模式不匹配的字符之间的所有空位置,因此,合乎逻辑的解决方案是使用 + 量词,a\+\|j 模式.