How do I substitute text only within my last visual selection, even mid-line?
Answer
:'<,'>s/\%Vold/new/g
Explanation
The \%V atom in a substitute pattern restricts matches to the exact bounds of the last visual selection, including within a single line. This goes beyond the '<,'> range, which applies the command to entire lines — \%V ensures only the visually highlighted characters are affected.
How it works
'<,'>— the range covering the last visual selection (set automatically when you press:in visual mode)\%V— a special regex atom that matches only inside the previously selected region- Together,
:'<,'>s/\%Vold/new/greplacesoldwithnewonly where it falls within the selection
Without \%V, using just '<,'>s/old/new/g would replace old anywhere on the selected lines — even outside what you highlighted.
Example
Given this line (brackets show the visual selection):
error: [connection timed] out at line 42
With connection timed visually selected, running :'<,'>s/\%V / _/g produces:
error: [connection_timed] out at line 42
The space in out after the selection is not affected.
Tips
- Works with both character-wise (
v) and line-wise (V) selections - Re-enter visual mode with
gvto re-select, then press:to rebuild the range - You can combine
\%Vwith other atoms:\%V\s\+matches runs of whitespace only inside the selection - In Neovim,
\%Valso works insidesearch()and:globalpatterns