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

How do I run a substitution only within the exact columns of a visual selection, not the whole line?

Answer

:'<,'>s/\%Vpattern/replacement/g

Explanation

When you press : after making a visual selection, Vim inserts '<,'> to restrict the substitution to the selected lines. But this still replaces matches anywhere on those lines, even outside the selection. The \%V atom restricts matching to only the characters that were inside the visual selection — including the exact column range.

How it works

  • '<,'> — restricts to the line range of the visual selection
  • \%V — a zero-width atom that matches only at positions inside the last visual selection
  • Together they restrict the substitution to exactly the highlighted region

This is especially powerful with visual block (<C-v>) selections, where '<,'> alone is meaningless for column restrictions.

Example

Given this text, with foo visually selected on both lines (columns 5–7 only):

aaa foo bbb foo
aaa foo bbb foo

Running :'<,'>s/foo/bar/g (without \%V) replaces all foo on those lines:

aaa bar bbb bar
aaa bar bbb bar

But :'<,'>s/\%Vfoo/bar/g replaces only the foo that was inside the selection:

aaa bar bbb foo
aaa bar bbb foo

Tips

  • Works with linewise (V), characterwise (v), and blockwise (<C-v>) selections
  • \%V matches the selection from the most recent visual mode; reselect with gv if needed
  • Combine with \%<V and \%>V to match just outside the selection boundaries
  • Works in search patterns too: /\%Vpattern highlights only matches inside the selection

Next

How do I match a pattern only when it is preceded or followed by another pattern, without including that context in the match?