2

当我注意到我贪婪的多行正则表达式在 Vim 中给出重叠匹配时,我感到很惊讶。正则表达式旨在匹配整个文本块或连续的非空行。

正则表达式显然匹配了我期望的所有内容(突出显示看起来正确),但是当使用n跳到下一个匹配而不是跳到下一个块时,它转到了当前块的下一行。

这是我使用的正则表达式(相当于(.+\n){1,}大多数正则表达式引擎):

\(.\+\n\)\{1,}

这应该匹配至少一个非空行,以及尽可能多的连续非空行,这是一个示例文本文件:

block 1
some stuff
more stuff

block 2
foo bar
baz qux

应用此正则表达式 ( /\(.\+\n\)\{1,}+ Enter) 后,两个块被正确突出显示,但我希望正则表达式只有两个匹配项,每个块一个。但是,当我按下n前进到下一个正则表达式匹配时,似乎每个非空行都与正则表达式匹配,所以我的光标将从第一行开始,n将其带到第二行,然后是第三行,然后到块的开头2等

如何更改我的正则表达式,以便我看到每个块的预期行为是一个匹配,以便n前进到下一个块,而不是下一行?

我也有兴趣知道此行为是否在某个地方的文档中,或者是否有更改此行为的选项。请注意,在搜索/替换中使用相同的正则表达式时,行为是我所期望的(替换只会应用两次,每个块一次)。

4

2 回答 2

4

以下正则表达式似乎有效:

\(\%^\|^\n\)\zs\(.\+\n\)\+

解释:

\(             # start of group
  \%^          # beginning of file
    \|         # OR
  ^\n          # a blank line
\)             # end of group
\zs            # start matching here
\(.\+\n\)\+    # at least one non-blank line

通过使用非常神奇的选项,长度可以减少一点:

\v(%^|^\n)\zs(.+\n)+

期待看看是否有人能提出更短的解决方案!

zigdon 的回答帮助我更好地理解了为什么这种行为是这样的。当n用于跳转到下一个匹配时,它从光标的当前位置搜索正则表达式的第一个匹配,即使下一个匹配位置包含在上一个匹配中。这就是为什么将正则表达式锚定到块的开头似乎是必要的。

感谢 Nolen Royalty 帮助我摆脱了第一组中不必要的前瞻。

于 2012-04-09T22:08:45.290 回答
2

由于您的匹配项显示“匹配一个或多个非空行”,因此它当然可以在同一段落中匹配多次。要解决此问题,您可以指定将光标放在匹配的末尾- 这意味着下一个匹配将从段落的末尾开始。您可以\zs使用 vim 中可用的零宽度字符来执行此操作:

\zs     Matches at any position, and sets the start of the match there: The
        next char is the first char of the whole match. |/zero-width|

所以你的比赛将变成:

\(.\+\n\)\{1,}\zs
于 2012-04-09T22:24:46.373 回答