How do I match a pattern only when it is NOT followed by another pattern in Vim regex?
Answer
\@!
Explanation
In Vim's regex engine, \@! is the negative lookahead assertion. It is placed after an atom and asserts that the atom does not match at the current position. This lets you write patterns like "match foo unless followed by bar" — without consuming any characters.
How it works
atom\@!— asserts thatatomdoes NOT match at this position (zero-width)- Unlike a normal match,
\@!does not advance the cursor — it only tests the surrounding context - Vim's lookahead family:
\@=(positive),\@!(negative),\@<=(positive lookbehind),\@<!(negative lookbehind)
Example
To find all occurrences of return that are not followed by a semicolon:
/return\(;\)\@!
This matches return only when it is not immediately followed by ;. If you used a regular /return[^;] pattern, it would also consume the non-semicolon character; \@! is zero-width.
Another example — highlight if not followed by err:
/if\(err\)\@!
Tips
- Use
\v(very magic) mode to simplify the syntax:/\vreturn(;)@! - The counterpart
\@<!is the negative lookbehind: match only when NOT preceded by a pattern - Combine with
\zs/\zeto set match boundaries while still using lookaheads for context - To match
foonot preceded by#:/(#)\@<!foo/