是否有上下文替换的标准?
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 a
s + 1(参见 source code comments)的位置再次尝试匹配。
请注意,a*
总是匹配,"wins",而 j
永远不会匹配。发生这种情况是因为优先顺序,第一个分支总是在 Vim 正则表达式中获胜。如果您替换 aaaj jjj
它将变成 xjx xjxjxj
因为该模式将匹配不匹配字符之前的每个位置。
正确的模式
用正则表达式替换时,您通常不想匹配与模式不匹配的字符之间的所有空位置,因此,合乎逻辑的解决方案是使用 +
量词,a\+\|j
模式.
在 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 a
s + 1(参见 source code comments)的位置再次尝试匹配。
请注意,a*
总是匹配,"wins",而 j
永远不会匹配。发生这种情况是因为优先顺序,第一个分支总是在 Vim 正则表达式中获胜。如果您替换 aaaj jjj
它将变成 xjx xjxjxj
因为该模式将匹配不匹配字符之前的每个位置。
正确的模式
用正则表达式替换时,您通常不想匹配与模式不匹配的字符之间的所有空位置,因此,合乎逻辑的解决方案是使用 +
量词,a\+\|j
模式.