我不确定答案,但可以分享预感。我认为这归结为完全零宽度的匹配/替换模式(例如/^\ze,
),即使从技术上讲它没有消耗任何东西,也必须将一些空灵的匹配索引移动一个。这样,它仍然可以继续进行下一场比赛,否则它将保持比赛在同一位置(如果有意义)。
您的例子似乎证明了这一点。下面是一个更具说明性的示例(更改输入以更好地显示匹配的内容)。
给出以下命令:
:s/\v(^|.)\ze(.|$)/<0\11\22>/g
在输入行上运行它将abcd
输出:
<01a2>a<0b1c2><0c1d2><0d12>
注意如何a
既匹配/替换(在<01a2>
),并且也无法比拟的如由a
在<01a2>a<0b1c2>
。这样可以防止ab
配对/替换。
我唯一能想到的是,这可以解释为某些匹配游标或匹配索引必须先a
被的第一个零宽度模式匹配后才移过第一个字符/^\ze.
换一种说法:
Input: abcd
Command: s/\v(^|.)\ze(.|$)/<0\11\22>/g
======================================
Match/Replace 1:
abcd => <01a2>abcd
^ ^
Matches /^ze.
Will move cursor by 1 after the zero-width /^\ze. match (or else it would be stuck there)
----------------
Match/Replace 2:
<01a2>abcd => <01a2>a<0b1c2>cd
^ ^
Matches /.\ze.
Consumes the '.' (in this case 'b'). Not entirely zero-width.
... and so on ...
因此,您的观点是,算法前进的唯一途径是不会卡住,因为它总是消耗非零宽度。由于第一个匹配为
^\ze,
,并且宽度为零,因此引擎将强制消耗,,
以超越起点。对?@EnricoMariaDeAngelis是的。在这种情况下,“使用非零宽度的东西”只是向前移动一个。至少这是我最好的猜测。
目前,这似乎是最好的答案。公认。