How do I substitute text only within my visual selection, not the whole line?
Answer
\%V
Explanation
The \%V atom in a search pattern restricts matching to the area of the last visual selection. When you use it inside a substitute command after making a character-wise visual selection, the replacement only applies to the exact characters you selected — not the entire line.
How it works
- Make a visual selection with
vorV - Press
:— Vim automatically inserts'<,'> - Type
s/\%Vpattern/replacement/g \%Vis a zero-width assertion that matches only if the position falls inside the last visual area
For linewise visual mode (V), this is similar to the range alone. The real power is with characterwise selections, where \%V restricts substitution to the exact column range selected rather than the entire lines.
Example
Given:
foo bar foo baz foo
↑ select from here to ↑
Visually select foo baz foo, then run :'<,'>s/\%Vfoo/qux/g:
foo bar qux baz qux
The first foo is untouched because it was outside the visual selection.
Tips
- Works with regex:
:'<,'>s/\%V\d\+/NUM/greplaces digits only in the selection - Combine with
\vfor very-magic syntax::'<,'>s/\v\%V\d+/NUM/g \%Vuses the marks'<and'>from the last visual selection, so you can reuse it even after leaving visual mode