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, without including that context in the match?

Answer

\@=

Explanation

Vim's regex engine supports zero-width lookahead and lookbehind assertions using the \@ family of atoms. These let you assert context around a match without consuming characters — the cursor does not advance past them, and they are not included in substitution results or visual highlights.

How it works

Syntax Name Meaning
A\@= Positive lookahead Match position if followed by A
A\@! Negative lookahead Match position if NOT followed by A
A\@<= Positive lookbehind Match position if preceded by A
A\@<! Negative lookbehind Match position if NOT preceded by A

The assertion applies to the atom immediately before \@.

Example

Match only the argument list portion of function calls (the part after ( in foo(bar)), without matching the function name:

/\(\w\+(\)\@<=\([^)]*\)/

Or: delete the semicolon only at end-of-line positions (not inside strings):

:%s/;\(\s*$\)\@=/,/g

Highlight return only when NOT followed by a value (bare return;):

/return\(\s*;\)\@=

Match words that are not preceded by #:

/\(#\)\@<!\w\+

Tips

  • These are distinct from \zs / \ze (which set match start/end for substitution). \@= / \@<= are true zero-width assertions and work in :match, syn match, search(), etc.
  • For long lookbehind patterns, add a length limit before \@<=: \{,20} matches up to 20 characters back: \(pattern\)\{,20}\@<=
  • Combine with \%V and \@<= for precision edits inside visual selections

Next

How do I quickly jump between function definitions or top-level blocks in a source file?