Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to repeat the same search and replace command over disjunct line ranges in Vim?

Tags:

replace

vim

I had a situation where I wanted to replace FOO with BAR through out a file. However, I only want to do it in certain places, say, between lines 68–104, 500–537, and 1044–1195. In practice, I dropped markers at the lines of interest (via ma, mb, mc, etc.) and ran the following:

:'a,'b s/FOO/BAR/g | 'c,'d s/FOO/BAR/g | 'e,'f s/FOO/BAR/g

I had to repeat this dozens of times with different search and replace terms s/CAT/DOG, etc., and it became a pain to have to rewrite the command line each time. I was lucky in that I had only three places that I needed to confine my search to (imagine how messy the command line would get if there were 30 or 40).

Short of writing a function, is there any neater way of doing this?

On a related note. I copied FOO to the s (search) register, and BAR to the r (replace) and tried running

:'a,'b s/\=@s/\=@r/ | 'c,'d s/\=@s/\=@r/ | 'e,'f s/\=@s/\=@r/

This would have saved me having to rewrite the command line each time, but, alas, it didn’t work. The replace bit \=@r was fine, but the \=@s bit in the search pattern gave me an error.

Any tips would be appreciated.

like image 953
Dave Doran Avatar asked Jun 22 '12 19:06

Dave Doran


2 Answers

If you need to perform a set of line-wise operations (like substitutions) on a bunch of different ranges of lines, one trick you can use is to make those lines look different by first adding a prefix (that isn't shared by any of the other lines).

The way I usually do this is to indent the entire file with something like >G performed on the first line, and then use either :s/^ /X/ commands or block-visual to replace the leading spaces with X on the lines I want.

Then use :g in conjunction with :s. eg:

:%g/^X/s/FOO/BAR/g
:%g/^X/s/BAZ/QUUX/g

Finally, remove the temporary prefixes.

like image 177
Laurence Gonsalves Avatar answered Oct 14 '22 09:10

Laurence Gonsalves


In order to get rid of the necessity to retype the same search pattern, substitution string and flags, one can simply use the :& command with the & flag:

:'a,'bs/pat/str/g | 'c,'d&& | 'e,'f&&

(See :help :& for details.)

like image 27
ib. Avatar answered Oct 14 '22 08:10

ib.