Vim中的正则表达式将匹配所有
以下刺痛中的字符最多为no.
?
foo, bar, and baz, no. 13, qux
换句话说,匹配必须是foo, bar, and baz,
我是正则表达式的新手,我在Stack上做了我的研究
溢出,一个建议是.+?(?= no.)
。但似乎有效
只有正则表达式的常规(perl?)风格,而不是
VIM。
请帮助。
也许有一个更简单的解决方案,我想要实现的目标。我的最终目标是将foo, bar, and baz
放在大括号中,并计划使用涉及正则表达式的全局替换命令。
答案 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 /\@=
)。
作为一个旁注,“将所有内容匹配到一个字符串”的常见方案是将一个带有开始和结束定界符的表达式匹配。例子:
"string literal"
; // comment\n
(其结束定界符是换行符); /regex/
。在许多此类情况下,结束分隔符实际上可能在要匹配的表达式内出现 escaped 。例如:
\"
中那样转义。\/
中那样被转义了(这是不正确的,例如/[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
^^^^^^^^^^^^^^^^^^^