How do I write a Vim regex lookahead that doesn't consume a capture group slot?
Answer
\%(pattern\)\@=
Explanation
Vim's lookahead assertion \@= confirms that the current position is followed by a pattern — without including those characters in the match. When combined with a non-capturing group \%(…\), the lookahead uses no capture group slot, keeping your \1, \2, … backreferences available for the parts of the match you actually care about.
How it works
\%(…\)— a non-capturing group: groups atoms for quantifiers or assertions without storing a backreference\@=— positive lookahead: succeeds if the preceding atom matches at the current position without consuming characters- Together,
\%(pattern\)\@=checks whether the upcoming text matchespattern, but neither consumes those characters nor stores them as\1
Contrast with the capturing form \(pattern\)\@=, which wastes a capture slot. When your pattern already uses \1, \2, etc. for substitutions, every extra \(…\) pushes your real captures to higher numbers — making patterns harder to read and maintain.
Example
Match a word that is immediately followed by a colon, and capture only the word (not the colon):
/\(\<\w\+\>\)\%(:\)\@=
Here \1 contains just the word. If you used \(:\)\@= instead, \2 would be wasted on the lookahead group.
In a substitution — prefix every label-style identifier (e.g. foo:) with >> without touching the colon:
:%s/\(\<\w\+\>\)\%(:\)\@=/>>\1/g
Before: foo: bar: baz
After: >>foo: >>bar: >>baz
Tips
- Use
\%(pattern\)\@!for a negative lookahead (match only when NOT followed bypattern) - Use
\%(pattern\)\@<=for a non-capturing lookbehind - Switch to
\v(very magic) to drop most backslashes:\v%(pattern)@= - Vim's help:
:help /\@=and:help /\%(