7

I have a multitude of files in each of which I want to, say, delete lines 1 through 55, add a comment leader (e.g., //) on lines 25 through 35, and then save the changes to a new file.

How can I do this automatically with Vim alone or together with the help of a Bash script?

ib.
  • 27,830
  • 11
  • 80
  • 100
user197292
  • 361
  • 3
  • 5

2 Answers2

18

Despite the fact that using ed or sed is a common practice ¹ in such cases, sometimes using Vim is much more convenient. Indeed, instead of writing an ed-like script somewhat blindly, it is often easier to first perform the desired manipulations with one of the files interactively in Vim:

vim -w log.vim file1.txt

and then repeat it for the rest of the files:

for f in file*.txt; do vim -s log.vim "$f"; done

For your example use case, the log.vim file will likely have contents similar to the following:

gg55dd:25,35s/^/\/\/ /
:w %_new
:q!

Note that to save a file with a new name you should not type it directly, but rather use the % substitution, as shown above—otherwise all the modifications of the subsequent files will be saved to the same file, overwriting its contents every time. Alternatively, you can duplicate the files beforehand and then edit the copies in place (saving each of them simply by issuing the :w command without arguments).

The advantage of this approach is that you can make all of the changes interactively, ensuring that you are getting the intended result at least on one of the files, before the edits are performed for the rest of them.


¹ Of course, you can use Vim in an ed-like fashion, too:

for f in file*.txt; do vim -c '1,55d|25,35s/^/\/\/ /|w!%_new|q!' "$f"; done
ib.
  • 27,830
  • 11
  • 80
  • 100
  • 1
    Never do that with the GUI version (gvim), see [my question](http://stackoverflow.com/questions/3981535/using-the-w-option-of-vim) and the related bug. With the GUI you must edit the scriptout. – Benoit May 12 '11 at 14:55
  • @Benoit Thanks for the warning! Since I never use GVim, it's unlikely that I could ever notice that behavior, while it's important to know. – ib. May 12 '11 at 15:59
6

You can accomplish this elegantly with ed, the unix line editor, the ancestor of vi.

fix_file () {
  ed -s "$1" <<-'EOF'
    1,55d
    25,35s_.*_// &_
    wq   
EOF
}

Now, for each file F you need, just execute fix_file F.

Jetchisel
  • 7,493
  • 2
  • 19
  • 18
ulidtko
  • 14,740
  • 10
  • 56
  • 88