Vim:正则表达式匹配直到某个字符串

3
在下面的字符串中,Vim中的哪个正则表达式可以匹配到no.之前的所有字符?请注意保留HTML标签。
(答案:)
foo, bar, and baz, no. 13, qux

换句话说,匹配必须是foo, bar和baz
我对正则表达式不熟悉,在Stack Overflow上做了一些研究,有一个建议是.+?(?= no.)。但似乎只适用于正则表达式的常规(perl?)风格,而不适用于Vim。
请帮忙。
也许有一个更简单的解决方案来实现我想要的目标。我的最终目标是将foo,bar和baz放在花括号中,并计划进行涉及正则表达式的全局替换命令。
4个回答

5
这个在vim中的正则表达式应该可以:
.*\zeno

例如,在你的代码中执行以下操作:
s/.*\zeno//

那一行将被更改为:

no. 13, qux

编辑

刚刚看到你的“最终目标”,你可以使用正则表达式:

:s/.*\zeno/{&}

如果您不想将逗号包装:

:s/.*\ze, no/{&}

嗨,肯特。谢谢你的快速回复。实际上,Vim会匹配一切直到包括“no.”的n。但是我希望它在“no.”之前停止。 - Mihai Nagy
如果您想看到从n之前的高亮显示,您可以在@MihaiNagy处使用.+\zeno - Kent

4
我的最终目标是将“foo,bar和baz”放在花括号中。 你可以尝试这样做:
:s/\v(.*)(, no\.)/{\1}\2/

1
这应该可以做到:

.*\( no[.]\)\@=

在这句话中,“no.”之前的所有字符都会被匹配。而“ \@=”则是向前查找,用于检查是否为“no.”。

1
到目前为止给出的所有答案对我来说都是错误的,因为它们执行了贪婪匹配。在一行中有几个“no”的情况下,它们将匹配到最后一个:
YES YES YES YES no YES YES no YES
^^^^^^^^^^^^^^^^^^^^^^^^^^^

然而,当将所有内容与某个字符串进行匹配时,目的通常是在第一次出现时停止:
YES YES YES YES no YES YES no YES
^^^^^^^^^^^^^^^^

为此,使用一个非贪婪正则表达式,例如:
.\{-}\(no\)\@=

\{-} 是非贪婪模式下的乘数 * 的替代品(请参见 :help non-greedy)。\@= 是正向预查,它将检查是否跟随“no”,但不会将其包含在匹配中(请参见 :help /\@=)。


作为一个附注,匹配“一直到某个字符串”的常见场景是匹配具有开放和关闭分隔符的表达式。例如:
  • C风格的字符串字面值"string literal"
  • C++样式的注释// comment\n(其结束定界符是换行符);
  • 正则表达式/regex/
在许多这种情况下,结束分隔符实际上可能出现在要匹配的表达式中。例如:
  • C风格的字符串文字可能包含双引号字符,在这种情况下,它必须以转义形式出现,如\"
  • 在C++注释中,由反斜杠前导的换行符将被忽略,副作用是注释继续在以下行上。
  • 正则表达式可以包含斜杠;在对正则表达式的语法采取过度简化的方法时,我们可以假设所有这些出现都是转义的,如\/(这不是真的,例如/[abc/]/是一个有效的Vim正则表达式,它匹配“a”、“b”、“c”之间的任何字符,“/”)。
因此,我们必须优化我们的正则表达式,以便它不会在转义的结束定界符上停止匹配。
让我们从错误的正则表达式开始,它匹配起始定界符“start”和结束定界符“stop”之间的任何内容(由于正向后查找\@<=和正向前查找\@=,它们不包括在匹配中):
\(start\)\@<=\_.\{-}\(stop\)\@=

比赛将在任何出现“stop”的情况下停止,即使它被转义。
test start test \stop test stop test
          ^^^^^^^

为了解决这个问题,我们可以将匹配任何字符(包括换行符)的\_.替换为\_[^\\]的分支(它匹配任何字符但不是反斜杠)和\\\_.(它匹配一个反斜杠后面跟着任何字符)。这意味着任何未转义的反斜杠都将被解释为转义序列的开始。反斜杠本身可以被转义,因此\\stop是一个转义的反斜杠,后面跟着一个真正的结束定界符。

这是布莱叶表达式:

\(start\)\@<=\(\_[^\\]\|\\\_.\)\{-}\(stop\)\@=

还有一些测试:

test start test \stop test stop test
          ^^^^^^^^^^^^^^^^^
test start test \\stop test stop test
          ^^^^^^^^
test start test \\\stop test stop test
          ^^^^^^^^^^^^^^^^^^^

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接