问题
In Vim, is there a way to search for lines that match say abc
but do not also contain xyz
later on the line? So the following lines would match:
The abc is the best
The first three letters are abc
and the following would not match:
The abc is the best but xyz is cheaper
The first three letters are abc and the last are xyz
I know about syntax like the following:
/abc\(xyz\)\@!
but that only avoids matching abcxyz
and not if there is anything in between, such as abc-xyz
. Using
/abc.*\(xyz\)\@!
also does not work because there are many positions later in the line where xyz
is not matched.
(I should note that on the command line I would do something like grep abc <infile | grep -v xyz
but I would like to do the above interactively in Vim.)
回答1:
Your attempt was pretty close; you need to pull the .*
that allows an arbitrary distance between the match and the asserted later non-match into the negative look-ahead:
/abc\(.*xyz\)\@!
I guess this works because the non-match is attempted for all possible matches of .*
, and only when all branches have been exhausted is the \@!
declared as fulfilled.
回答2:
I always find it weird, that you need to escape brackets in vim, so I try to use the "very magic" mode most of the time, activated with \v
:
/\vabc(.*xyz)@!
回答3:
Although your question is about lookahead, I found it while searching for lookbehind. Thus, I post the solution to lookbehind so that others may find it.
If you search for pattern2
not preceded by pattern1
, that is negative lookbehind, search for:
\(pattern1\)\@<!pattern2
回答4:
This works for me /abc\(.*xyz\)\@!
回答5:
I think I'd write this as /abc\(\(xyz\)\@!.\)*$
I'm not sure whether this is faster than other suggestions (I think it might be since it tests each position only once) but it makes conceptual sense as:
"abc followed by anything which is not xyz, any number of times until end of line"
I like that better than "abc followed by anything not followed by xyz" as in the other patterns mentioned.
来源:https://stackoverflow.com/questions/21148467/is-there-a-way-to-do-negative-lookahead-in-vim-regex