首页 > 解决方案 > 为什么 vim 在这种情况下会使用 \ze 之后的模式?

问题描述

仅供参考,这个问题源于这个sed答案

给定一个 5 列 CSV 行,所有 5 列都为空,即仅包含 的行,,,,,我认为以下vim-ex命令应插入hello所有 5 个位置:

:s/\v(^|,)\ze(,|$)/\1hello/g

但是它没有,因为输出是

hello,,hello,hello,hello

第一个hello被插入是因为^\ze,在行首匹配。然而,这似乎,被命令消耗掉了。是这样吗?如果是这样,为什么?

标签: regexvimregex-lookarounds

解决方案


我不确定答案,但我可以分享一个预感。我认为这归结为完全零宽度的匹配/替换模式(例如/^\ze,)必须将一些空灵的匹配索引移动一,即使它在技术上没有消耗任何东西。这样它仍然可以进入下一场比赛,否则它只会在相同的位置保持匹配(如果这有意义的话)。

你的例子似乎证明了这一点。下面是一个更具说明性的示例(更改输入以更好地显示匹配的内容)。

给定以下命令:

:s/\v(^|.)\ze(.|$)/<0\11\22>/g

对输入行运行它将abcd输出:

<01a2>a<0b1c2><0c1d2><0d12>

请注意如何a匹配/替换(in <01a2>),并且不匹配,如ain所示<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 ...

推荐阅读