How do I use zero-width lookbehind assertions in Vim search patterns to match text only when preceded (or not preceded) by a pattern?
Answer
\@<= and \@<!
Explanation
Vim's \@<= and \@<! atoms let you write zero-width lookbehind assertions — they check what comes before the match position without consuming characters. This unlocks highly precise search and substitution patterns that would otherwise require capturing groups and complex replacement logic.
How it works
Both atoms are placed immediately after a pattern they test against:
\(LOOKBEHIND\)\@<=MATCH— matchesMATCHonly if preceded byLOOKBEHIND\(LOOKBEHIND\)\@<!MATCH— matchesMATCHonly if not preceded byLOOKBEHIND
The lookbehind pattern is wrapped in \(\) so Vim knows its extent. Neither the lookbehind text nor any position is consumed — the match starts exactly at MATCH.
Example
Given:
return foobar
call foobar
To find foobar only when preceded by return :
/\(return \)\@<=foobar
This matches only the first foobar, leaving the second untouched. Use in a substitution:
:%s/\(return \)\@<=foobar/baz/g
Result:
return baz
call foobar
Tips
- The lookahead counterpart is
\@=(positive) and\@!(negative) — placed after the pattern they test - For very magic mode (
\v), write%(LOOKBEHIND)@<=MATCHwithout extra backslashes - Variable-length lookbehinds are allowed in Vim's regex engine (unlike some other engines)
- Combine with
\@<=in substitutions to prepend or append text without re-capturing the prefix