Vim:正则表达式匹配一个字符串

时间:2013-11-12 16:37:19

标签: regex vim

Vim中的正则表达式将匹配所有 以下刺痛中的字符最多为no.

foo, bar, and baz, no. 13, qux

换句话说,匹配必须是foo, bar, and baz,

我是正则表达式的新手,我在Stack上做了我的研究 溢出,一个建议是.+?(?= no.)。但似乎有效 只有正则表达式的常规(perl?)风格,而不是 VIM。

请帮助。

也许有一个更简单的解决方案,我想要实现的目标。我的最终目标是将foo, bar, and baz放在大括号中,并计划使用涉及正则表达式的全局替换命令。

4 个答案:

答案 0 :(得分:4)

vim中的这个正则表达式应该

.*\zeno

e.g。你这样做了:

s/.*\zeno//

该行将更改为:

no. 13, qux

修改

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

:s/.*\zeno/{&}

如果您不想包装逗号:

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

答案 1 :(得分:4)

  

我的最终目标是将'foo,bar和baz'放在大括号中

你可以尝试

:s/\v(.*)(, no\.)/{\1}\2/

答案 2 :(得分:1)

这应该做:

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

在单词中,所有字符直到匹配“no。”的字符集。前方匹配\@=执行“否”检查。

答案 3 :(得分:0)

到目前为止,所有给出的答案对我来说都是错误的,因为它们执行的是贪婪匹配。在多次出现“否”的行中,它们将匹配最后一个:

YES YES YES YES no YES YES no YES
^^^^^^^^^^^^^^^^^^^^^^^^^^^

但是,将所有内容匹配为一个字符串的目的通常是在第一次出现时就停止:

YES YES YES YES no YES YES no YES
^^^^^^^^^^^^^^^^

为此,请使用 non-greedy 正则表达式,例如:

.\{-}\(no\)\@=

\{-}是乘数*的非贪婪替代(请参阅:help non-greedy)。 \@=是一个积极的前瞻性,它将检查是否跟随“ no”,但不会将其包括在比赛中(请参阅:help /\@=)。


作为一个旁注,“将所有内容匹配到一个字符串”的常见方案是将一个带有开始和结束定界符的表达式匹配。例子:

  • C风格的字符串文字"string literal";
  • C ++样式的注释// comment\n(其结束定界符是换行符);
  • 正则表达式/regex/

在许多此类情况下,结束分隔符实际上可能在要匹配的表达式内出现 escaped 。例如:

  • C样式的字符串文字可能包含双引号字符,在这种情况下,它必须像\"中那样转义。
  • 在C ++注释中,以反斜杠开头的换行符将被忽略,其副作用是注释在下一行继续。
  • 正则表达式可以包含斜杠;在对正则表达式的语法过于简化的情况下,我们可以假定所有此类出现都像在\/中那样被转义了(这是不正确的,例如/[abc/]/也是一个有效的Vim regex,它与任何“ a”,“ b”,“ c”,“ /”之间的字符)。

因此,我们必须优化正则表达式,以使其不会在结束分隔符的转义出现时停止。

让我们从错误的正则表达式开始,该正则表达式匹配开始定界符“ start”和结束定界符“ stop”之间的任何内容(由于\@<=和正前瞻\@=):

\(start\)\@<=\_.\{-}\(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
          ^^^^^^^^^^^^^^^^^^^