1

I have a number of files (more than a hundred) that I want to process using Vim. A sample of the files’ contents is as follows:

xyz.csv        /home/user/mydocs/abc.txt

/home/user/waves/wav.wav , user_wav.wav  

I want this to be replaced by:

xyz.csv      /var/lib/mydir/abc.txt
/var/sounds/wav.wav , wav.wav  

In each of the files, the changes I need to make are the same. My questions are:

  1. Can I use Vim search and replace functionality by calling it from within a Bash script?

  2. If so, how do I go about it?

P.S. I have searched StackOverflow for similar questions and found some answers using ex scripts, etc. I want to know how I can call an ex script from within a bash script.

ib.
  • 27,830
  • 11
  • 80
  • 100
Sriram
  • 10,298
  • 21
  • 83
  • 136
  • I would use a sed instead of what you're trying to do with vim – Grammin Aug 04 '11 at 17:08
  • See [the answer](http://stackoverflow.com/questions/5932102/automated-edit-of-several-files/5932840#5932840) to similar [question](http://stackoverflow.com/questions/5932102/automated-edit-of-several-files). – ib. Aug 05 '11 at 01:54

5 Answers5

5

While vim is quite powerful, this is not something I would normally use vim for. It can be done using a combination of common command line utilities instead.

I've assumed that the blank line in your example above is actually blank and does not contain spaces or any other whitespace characters. You can use the following to do what you want.

sed  -e "s,/home/user/mydocs,/var/lib/mydir," -e "s,/home/user/waves,/var/sounds," -e "/^$/d" file1

You can use that command together with find and a for loop to do this for a bunch of files:

for file in `find . -maxdepth 1 -type f`
do
    sed  -e "s,/home/user/mydocs,/var/lib/mydir," -e "s,/home/user/waves,/var/sounds," -e "/^$/d" $file
done

In the for loop, the find command above limits the output to all files in the current directory (including dot files), assigning each line from the output of find to the file variable and then running the sed command posted earlier to transform the file the way you want it to be transformed.

mattr-
  • 5,333
  • 2
  • 23
  • 28
2

This is how you'd invoke an ed script from bash:

ed filename <<END
/^$/d
%s|/home/user/mydocs|/var/lib/mydir|
%s|/home/user/waves|/var/sounds|
%s|, user_|, |
w
q
END
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
1

To answer with vim, you can do

vim -e 'bufdo!%s:\(xyz.csv        \)/home/user/mydocs/\(abc.txt\n\)\n.*:\1/var/lib/mydir/\2/var/sounds/wav.wav , wav.wav:' -e 'xa' FILES 

Note, I had assumed, that the second line is statically replaced, as it had looked like in the question.

If you don't like writing long lines in your script, you can create a file like:

s/FOO/BAR/
" several replacement and other commands
w " write the file
bd " if you want to

Then do:

vim -e "buffdo!source /your_scriptfile" -e "x" FILES

HTH

Zsolt Botykai
  • 50,406
  • 14
  • 85
  • 110
1

If all the editing consists in a series of substitutions, the most idiomatic way of accomplishing it using Vim would be the following.

  1. Open all the target files at once:

     vim *.txt
    
  2. Run the substitution commands on the loaded files:

     :argdo %s#/home/user/mydocs#/var/lib/mydir#
     :argdo %s#/home/user/waves#/var/sounds#
     :argdo %s#, \zsuser_##
     ...
    
  3. If changes are correctly made, save the files:

    :wall
    

If the editing you want to automate could not be expressed only in substitutions, record a macro and run it via the :normal command:

:argdo norm!@z

(Here z is the name of the macro to be run.)

Lastly, if the editing should be performed from time to time and needs to be stored in a script, try using the approach described in the answer to a similar question.

ib.
  • 27,830
  • 11
  • 80
  • 100
0

Answer

While most vim users would be aware of the % motion command for executing inclusive commands on the whole document in the current buffer. Most modern versions of vim (ie 6.x+) support actions on regex searches for exclusive actions like so:

:/regex/substitute/match/replace/ # as vim command line
+"/reges/s/match/replace"         # as bash cli parameter

This breaks down into vim doing the following,

  1. search for regex and put the cursor at start of found point
  2. call internal substitute function (see :help s or :help substitute) [ could be other commands ]
  3. match string with regex for substitution
  4. replace with new string value

Effectively it operates the same as the :global command.

Notes

Command after regex search can be any command, including '!"shell command"' filter commands.

Reference Help

  • :help global
  • :help substitute
  • :help filter
Dwight Spencer
  • 1,472
  • 16
  • 22