Search code examples
regexvimregex-lookarounds

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


Solution

  • The .* allows an arbitrary distance between the match and the non-match, which is asserted later.
    You need to pull the .* into the negative look-ahead:

    /abc\(.*xyz\)\@!
    

    Possible Reason
    The non-match is attempted for all possible matches of .*, and the \@! is declared as fulfilled only when all branches have been tried.