a little vi trick

Posted April 28th, 2009 by j00p34

An update to my previous article My vi first steps

I use vi instead of command line editors to do mass replacing of blocks and editing many files in the following way:

say I know all files I need to edit in the current directory contain the text foo and the rest of the files don't.

I open all files containing foo in vi:

vi $(grep -l 'foo' *)

start macro recording to register q

qq

search and replace in the whole file

/%s/foo/bar/g

next file

:wn

stop recording

q

execute the macro many times to be sure we got them all, if we get to the end vi will complain that it can't go beyond the last file.

200@q

This is obviously not the most efficient way of doing this particular replace, but you can imagine the time it saves when you don't need to dream up and test a complex regular expression because in vi you can do things like search for a pattern and replace one line beneath it. Or make several changes at once.
Little imagination is needed to come up with very complex changes to lots of files with a little knowledge of vi, while keeping your sanity.

Like this one:

Keeping macros available between sessions is needed for this one. Add this line to your ~/.vimrc file:
set viminfo=%,'50,\"100,n~/.viminfo
unless something like this is already there of course.
100 saves the first 100 lines of each register in the viminfo file. Making it available for all future sessions until you overwrite it.

or use the marvin vim plugin:

http://www.vim.org/scripts/script.php?script_id=2154

Now you can easily run vimdiff on two files if you have one containing the block of text you want to put in all the other files.

vimdiff file1 file2

This opens the two files in comparison mode in vim file1 on the left file2 on the right.
Navigate to the block you want to use. Differences are highlighted so it's easy to find. Now switch screens with CTRL-w,CTRL-w (that's CTRL-w twice) and copy the lines or words or block you need.
To get a block:
Go to the start of your block and press v for visual mode.
Go to the end of the block and press y for yank.

quit the files with :x (twice)

The rest is the same as before, just open multiple files with vi * or vi $(grep -l 'pattern' *)
And record a macro which deletes the content you want replaced and paste the current buffer(recorded in the previous session) using the p in it's place.

Or you can already record the macro in the first opened files, just close the file you don't want to edit using :x and record the macro replacing the buffered text at once. The macro and the buffer will both be available across settings.

Thanks to Linuxoneliner.com for the code to open all files containing pattern in vi.

Am I doing things overly complex? Do you know a better way of doing this? Have more creative things we can do with vi? Leave a comment! Comments can take a while before they get published (other time zone)


use perl;

Anonymous 2 years 41 weeks 21 min 26 sec ago

perl -i -pe 's/foo/bar/g' `grep -l foo *`

or if you prefer to replace recursively:

find . -type f -exec grep -l foo "{}" \; | cut -d: -f1 | xargs perl -i -pe 's/foo/bar/g'

Sed

Anonymous 2 years 41 weeks 2 hours 12 min ago

sed 's/foo/bar/g' *

use sed

Anonymous 2 years 41 weeks 1 day 38 min ago

Not tested, but I'd do something like this:

sed -i "s/foo/bar/g" `grep -l foo *`

The "grep -l" in the backquotes returns a list of filenames.
"sed -i" edits files in place.

very nice! but the Unix's

Anonymous 2 years 41 weeks 4 hours 37 min ago

very nice!
but the Unix's sed has not -i option :(

regards!

you can also do something

Anonymous 2 years 41 weeks 1 day 3 hours ago

you can also do something like:
for i in *foo*; do
echo -e "% s/foo/bar/g\nwq\n"|ed $i
done

Note: not tested :)

bufdo

Anonymous 2 years 41 weeks 1 day 8 hours ago

Hi,

for your first trick, you can use bufdo to run a command on all open buffers. So,
":bufdo! %s/foo/bar/g"
when vim opens the files will work just as well

add cool to google

Add to Google

Cool's blog feed

site feed

Syndicate content

don't forget to vote if you find something useful!!