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

How do I match a pattern only when it is preceded or followed by another pattern using Vim regex?

Answer

\@<= and \@=

Explanation

Vim's regex engine supports zero-width lookahead and lookbehind assertions using the \@ atom. These let you match text based on what surrounds it, without including the surrounding text in the match itself. This is essential for complex search-and-replace operations where context determines what should change.

How it works

The four assertion atoms:

  • \(pat\)\@<=positive lookbehind: match position preceded by pat
  • \(pat\)\@<!negative lookbehind: match position NOT preceded by pat
  • \(pat\)\@=positive lookahead: match position followed by pat
  • \(pat\)\@!negative lookahead: match position NOT followed by pat

The pattern being asserted must be grouped in \(\) and the \@... atom follows immediately.

Example

Replace foo only when it appears before bar (positive lookahead):

:%s/foo\(bar\)\@=/FOO/g

In foobar foobaz, only the first foo becomes FOO.

Match bar only when NOT preceded by foo (negative lookbehind):

/\(foo\)\@<!bar

In foobar barbell, only barbell's bar matches.

Tips

  • In \v (very magic) mode the syntax shortens: @<=, @<!, @=, @!
  • Lookbehind with variable-length patterns has performance implications — keep them as specific as possible
  • For simple cases, \zs and \ze (which reposition match boundaries) are often easier; reach for \@<= when you need true zero-width context conditions

Next

How do I browse the full commit history of the current file using vim-fugitive?