Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to do negative lookahead in vim regex?

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.)

like image 484
Greg Hewgill Avatar asked Jan 15 '14 21:01

Greg Hewgill


People also ask

How do you write negative lookahead in regex?

Negative lookahead That's a number \d+ , NOT followed by € . For that, a negative lookahead can be applied. The syntax is: X(?! Y) , it means "search X , but only if not followed by Y ".

Can I use regex lookahead?

Lookahead assertions are part of JavaScript's original regular expression support and are thus supported in all browsers.

What does lookahead do regex?

Lookahead is used as an assertion in Python regular expressions to determine success or failure whether the pattern is ahead i.e to the right of the parser's current position. They don't match anything. Hence, they are called as zero-width assertions.

What is lookaround in regex?

Zero-Width Matches As we've seen, a lookaround looks left or right but it doesn't add any characters to the match to be returned by the regex engine. Likewise, an anchor such as ^ and a boundary such as \b can match at a given position in the string, but they do not add any characters to the match.


1 Answers

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.

like image 193
Ingo Karkat Avatar answered Sep 27 '22 18:09

Ingo Karkat