Vim多线正则表达式提供重叠匹配

时间:2012-04-09 22:01:57

标签: regex vim vi

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

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

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

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

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

block 1
some stuff
more stuff

block 2
foo bar
baz qux

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

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

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

2 个答案:

答案 0 :(得分: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

通过使用very magic选项,可以减少一点长度:

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

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

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

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

答案 1 :(得分:2)

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

\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