vimtricks.wiki Concise Vim tricks, one at a time.

How do I search for a pattern only when it's preceded or followed by another pattern?

Answer

/\(pattern\)\@<=target or /target\(pattern\)\@=

Explanation

Vim supports zero-width assertions (lookahead and lookbehind) in its regex engine. These let you match text only when it appears near another pattern, without including that context in the match itself.

Lookbehind: match after a pattern

" Match 'bar' only when preceded by 'foo'
/\(foo\)\@<=bar

" With very magic mode (cleaner syntax)
/\v(foo)@<=bar

Lookahead: match before a pattern

" Match 'foo' only when followed by 'bar'
/foo\(bar\)\@=

" With very magic mode
/\vfoo(bar)@=

Negative variants

" Match 'bar' NOT preceded by 'foo'
/\(foo\)\@<!bar

" Match 'foo' NOT followed by 'bar'
/foo\(bar\)\@!

Practical examples

" Find 'print' not inside a comment (not preceded by #)
/\(#.*\)\@<!print

" Find variable assignments (word followed by ' = ')
/\v\w+( \= )@=

" Find opening braces not preceded by 'if' or 'for'
/\v(if|for)@<!\s*\{

" Replace 'get' only when followed by uppercase (method names)
:%s/\vget([A-Z])@=/fetch/g

Tips

  • Use \v (very magic mode) to avoid excessive escaping
  • @<= is lookbehind, @= is lookahead
  • @<! is negative lookbehind, @! is negative lookahead
  • Lookbehind in Vim can have variable length (unlike most regex engines)
  • Performance: @<= with complex patterns can be slow on large files
  • Documented under :help /\@= and :help /\@<=

Next

How do I run the same command across all windows, buffers, or tabs?