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

How do I restrict a substitute command to only the text within my last visual selection using the percent-V atom?

Answer

:s/\%Vfoo/bar/

Explanation

The \%V atom in Vim's regex engine matches only within the area of the last visual selection. Unlike the '<,'> range that restricts which lines are affected, \%V restricts which columns are matched within those lines — making it essential for blockwise visual selections and for avoiding partial-line matches at the selection boundaries.

How it works

  • \%V is a zero-width atom that asserts the current match position is inside the last visual selection
  • When combined with :'<,'>s/\%Vpattern/replacement/, the range limits which lines are searched while \%V limits which columns match
  • Without \%V, a line-range substitute can match anywhere on the selected lines, including text outside the visually selected columns in a blockwise selection

Example

Given this text with a blockwise (<C-v>) selection covering only the numbers:

foo 123 bar
baz 456 qux

Running :'<,'>s/\%V\d/X/g replaces only the visually selected digits:

foo XXX bar
baz XXX qux

Without \%V, the same command would also match any digits outside the selected columns.

Tips

  • \%V uses the last visual selection — reusable even after leaving visual mode
  • Combine with gv to reselect the last visual area before running the command
  • Works with all visual modes: characterwise v, linewise V, and blockwise <C-v>
  • Available in search patterns too: /\%Vword highlights occurrences only within the visual area

Next

What is the difference between the inner word (iw) and inner WORD (iW) text objects in Vim?