问题
What regular expression in Vim will match all
characters up to no. in the below sting?
foo, bar, and baz, no. 13, qux
In other words the match must be foo, bar, and baz,
I'm new with regular expressions, did my research here on Stack
Overflow, and one suggestion is .+?(?= no.). But it seems to work
only with the regular (perl?) flavour of regular expressions, not in
Vim.
Please, help.
Maybe there's a simpler solution to what I'm trying to achieve. My ultimate goal is to put foo, bar, and baz in curly brackets, and I planned to to a global substitution command involving regular expressions.
回答1:
My ultimate goal is to put 'foo, bar, and baz' in curly brackets
You could try
:s/\v(.*)(, no\.)/{\1}\2/
回答2:
this regex in vim should do
.*\zeno
e.g. you do this on your line:
s/.*\zeno//
that line would be changed into:
no. 13, qux
EDIT
just saw your "ultimate goal", you can just use the regex:
:s/.*\zeno/{&}
if you don't want to wrap the comma:
:s/.*\ze, no/{&}
回答3:
This should do:
.*\( no[.]\)\@=
In words, all characters up to the set of characters matching " no.". The match look ahead, \@=, performs the check for " no.".
回答4:
All answers given so far are wrong to me, because they perform a greedy match. In a line where there are several occurrences of “no”, they will match up to the last one:
YES YES YES YES no YES YES no YES
^^^^^^^^^^^^^^^^^^^^^^^^^^^
However, the purpose when matching everything up to some string is often to stop at the first occurrence:
YES YES YES YES no YES YES no YES
^^^^^^^^^^^^^^^^
For this purpose, use a non‐greedy regular expression, such as:
.\{-}\(no\)\@=
\{-} is the non‐greedy alternative to the multiplier * (see :help non-greedy). \@= is a positive look‐ahead, it will check that “no” follows but will not include it in the match (see :help /\@= ).
As a side note, a common scenario for “matching everything up to some string” is to match an expression with opening and closing delimiters. Examples:
- C‐style string literals
"string literal"; - C++‐style comments
// comment\n(whose closing delimiter is the newline character); - regular expressions
/regex/.
In many such cases, the closing delimiter may in fact appear escaped inside the expression to be matched. For instance:
- A C‐style string literal may contain the double‐quote character, in which case it must appear escaped as in
\". - In a C++ comment, a newline character preceeded by a backslash is ignored, with the side effect that the comment continues on the following line.
- A regular expression may contain a slash; in an overly simplistic approach to the syntax of regular expressions, we may assume that all such occurrences are escaped as in
\/(this is not true, for example/[abc/]/is also a valid Vim regex which matches any character among “a”, “b”, “c”, “/”).
Hence, we must refine our regular expression so that it does not stop on escaped occurrences of the closing delimiter.
Let’s start with the wrong regular expression that matches anything between a starting delimiter “start” and a closing delimiter “stop” (which are not included in the match, thanks to the positive look‐behind \@<= and the positive look‐ahead \@= ):
\(start\)\@<=\_.\{-}\(stop\)\@=
The match will stop at any occurrence of “stop”, even if it is escaped:
test start test \stop test stop test
^^^^^^^
To fix this behaviour, we may replace \_. (which matches any character, including newlines) by the disjunction of \_[^\\] (which matches any character but a backslash) and \\\_. (which matches a backslash followed by any character). This means that any non‐escaped backslash will be interpreted as the beginning of an escaping sequence. Backslashes themselves can be escaped, so that \\stop is an escaped backslash followed by a true closing delimiter.
Here is the Braille expression:
\(start\)\@<=\(\_[^\\]\|\\\_.\)\{-}\(stop\)\@=
and some tests:
test start test \stop test stop test
^^^^^^^^^^^^^^^^^
test start test \\stop test stop test
^^^^^^^^
test start test \\\stop test stop test
^^^^^^^^^^^^^^^^^^^
来源:https://stackoverflow.com/questions/19934777/vim-regular-expression-to-match-up-to-a-string