Vim 多行正则表达式给出重叠匹配
Posted
技术标签:
【中文标题】Vim 多行正则表达式给出重叠匹配【英文标题】:Vim multiline regex gives overlapping matches 【发布时间】:2012-04-22 06:04:32 【问题描述】:当我注意到我的贪婪多行正则表达式在 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 前进到下一个块,而不是下一行?强>
我也有兴趣了解此行为是否在文档中的某处,或者是否有更改此行为的选项。请注意,在搜索/替换中使用相同的正则表达式时,行为是我所期望的(替换只会应用两次,每个块一次)。
【问题讨论】:
【参考方案1】:以下正则表达式似乎有效:
\(\%^\|^\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 帮助我摆脱了第一组中不必要的前瞻。
【讨论】:
据我所知\(\%^\|^\n\)\zs\(.\+\n\)*
完成了同样的事情。不过,它仍然令人沮丧。
@NolenRoyalty 如果有几个连续的空行,你将匹配一些空行(零宽度匹配),但它确实引导我到\(\%^\|^\n\)\zs\(.\+\n\)\+
,它没有同样的问题。还是很丑!【参考方案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
【讨论】:
这使我可以跳到每个块的末尾,这对于正则表达式的简单性来说是很好的,但如果可能的话,我希望将整个块包含在匹配中。 该块将包含在匹配中,只是光标将定位在它的末尾。还是你的意思是别的? 我所说的“包含在匹配中”的意思是,如果您在搜索/替换中使用相同的正则表达式,则匹配中包含的所有内容都将被替换。另一个等效含义是“突出显示的文本”。以上是关于Vim 多行正则表达式给出重叠匹配的主要内容,如果未能解决你的问题,请参考以下文章