27

I often have text in columns and need to replace some things without clobbering similar stuff on the same line... a simple example follows:

vim visual block-mode screenshot

Suppose I have highlighted the text in grey with vim visual block mode, and want to replace 80 with 81; however, I only want replacements within the highlighted visual block.

I have already tried Cntlv : s/80/81/g; however, that replaces text inside and outside the visual block. (based on Randy's feedback, it's because : s is a line-wise command).

I know I could use a line-wise visual block replace in this particular instance ( Shiftv : s/80\.1/81.1/g ); however, I'm trying to find a general solution for the problem of having no easy means to replace within a non line-wise visual block (isn't this the kind problem that visual block mode is supposed to help solve?). Answers requiring confirmation like : s/80/81/gc, are not what I am looking for.

I will restate the question for clarity: How can I replace 80 with 81 by using vim's visual block mode highlight?

DJMcMayhem
  • 7,285
  • 4
  • 41
  • 61
Mike Pennington
  • 41,899
  • 19
  • 136
  • 174

3 Answers3

28

You need to add \%V to your pattern. From :help \%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.

OP EDIT: the explicit solution is to to use : s/\%V8\%V0/81/g

ZyX
  • 52,536
  • 7
  • 114
  • 135
Randy Morris
  • 39,631
  • 8
  • 69
  • 76
  • Exactly what I was looking for; it's interesting that I don't need `\%V` in line-wise block mode. – Mike Pennington Jun 03 '11 at 18:58
  • 2
    Because ':s' is a linewise operation. The advantage of adding this is that even if you left visual mode you can still operate on the last visual selection with '\%V' in your pattern. – Randy Morris Jun 03 '11 at 19:12
  • For me to understand this I treat `\%` like a regex escape character, `\` and `V` like `b` in `\b` for a word boundary where `\%V` is the boundary of the selection. – Yzmir Ramirez Jul 31 '14 at 23:30
  • 2
    @YzmirRamirez This way of understanding `\%V` is completely incorrect. `\%V` is a zero-width atom that matches *inside* the visual selection. If you select one character (e.g. `1`) and use `\%V1\%V` you will see that there is no match because second character is not inside the selection. Also if it *was* boundary using `\%V2` on selection `123` would not match `2`. – ZyX Oct 30 '14 at 22:55
  • @MikePennington For the reason explained above your edit is not correct. Correct regex is `\%V8\%V0`, *not* `\%V80\%V`. – ZyX Oct 30 '14 at 22:57
7

The visual selection block should be identifiable with %V

:'<,'>s/\%V80/81/g
Mikhail
  • 8,692
  • 8
  • 56
  • 82
6

The solution is obviously the \%V regex atom, but note, that this it still a little bit buggy.

Update: It's no bug. This thread explains the behaviour.

Christian Brabandt
  • 8,038
  • 1
  • 28
  • 32
  • 1
    Thank you for your response. What kind of buggy behavior have you seen with `\%V`? – Mike Pennington Jun 08 '11 at 13:52
  • @ChristianBrabandt It would be more helpful if you a) said that `\%V` matches inside the regex (see my comment to the accepted answer) and b) deleted or unproved the above comment which states that `\%V` is not zero-width. // I think it is your edit that made this question appear in the RSS. – ZyX Oct 30 '14 at 23:02