48

How does one get vim to replace a character within the visual selection only and not elsewhere on the line? Example:

  • Line: int arr[] = { 00 01 02 03 04 05 05 /* ... lots more like this*/};
  • Visual Selection: { 00 01 02 03 04 05 05 /*... lots more like this*/}
  • Command: :'<,'>s/\ /\,0x/g
  • Expected: int arr[] = {0x00,0x01,0x02,0x03 /* and so on*/};

After performing these actions however, the actual result is:

int,0xarr[],0x=,0x{0x00,0x01,0x02,0x03 /* and so on*/};

Is there a way to modify the command above to produce the expected result? Doesn't '< and '> define the range on which the search (and replace) commands work?

1
  • 2
    I don't know the answer, but I know that :substitute operatores on a line by line basis, which explains what you are seeing in your example. Feb 19, 2015 at 8:03

5 Answers 5

61
:'<,'>s/\%V\ /\,0x/g

%V matches inside the visual area. See :help %V.

2
  • 6
    It should be mentioned, that this solution only verifies, that the start of the match is inside the visual selection. Feb 22, 2019 at 12:28
  • This does not seem to work if the visual selection contains a \ itself. If that is the case the visual selection will deselect.
    – Bono
    Sep 7, 2021 at 15:05
25

There’s \%V for that, see :h %V:

%V

Match inside the Visual area. When Visual mode has already been stopped match in the area that gv would reselect. This is a /zero-width match. To make sure the whole pattern is inside the Visual area put it at the start and end of the pattern, e.g.: > /%Vfoo.*bar%V

To replace foo by bar in the selection only, use:

:'<,'>s/\%Vfoo\%V/bar/
:'<,'>s/\%Vfoo\%V/bar/g
:'<,'>s/\%Vfoo\%V/bar/cg

In this particular case:

:'<,'>s/\%V\ \%V/\,0x/g
4

If you want to substitute within a visual block, you can use the vis.vim plugin.

http://vim.wikia.com/wiki/Applying_substitutes_to_a_visual_block

To install:

Download vis.vba.gz from http://www.drchip.org/astronaut/vim/index.html#VIS

# Open vis.vba.gz in Vim 7.1 or later.
vim vis.vba.gz

# Source the open file.
:so %

# Quit Vim
:q

Once installed:

ctrl-v to enter visual-block mode
Move to select the block you want
:B s/pattern/newtext/

When you type :B, you will see this

:'<,'>B 

That's fine, it's just vim saying that the command will apply to the currently selected visual block.

Even better, you can perform any Ex command on the visual block, not just substitutions. For example :B !sort.

3

Set vnoremap :s :s/\%V\%V/<Left><Left><Left><Left>.

It adds \%V guards and places cursor in the middle. Use End or Ctrl+E to enter replacement pattern.

1

Following @dessert, I found the description and example a little confusing until I recognized %V wraps pattern.

:'<,'>s/pattern/newtext/

Becomes,

:'<,'> s/ \%V foo \%V / bar /

Remove the spaces,

:'<,'>s/\%Vfoo\%V/bar/gc

(because I always regret not using g-lobal, c-onfirmation)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.