I have been using vim almost exclusively for file editing on any operating system that I use, whether Mac OS X, Linux or Windows. Here is an example how to use vim to build and execute bash commands using vim's regular expressions.
Often I manipulate log and data files. I need to copy a group of files. Each file in the group have date stamp and I need to make copies with different date stamps.
Here is how you can create bash commands to copy group of files from vim.
My directory contains four files and a directory called abc:
> ls abc abc.4.0.20100204.body abc.4.0.20100204.header abc.4.0.20100204.seqnums abc.4.0.20100204.session
I need to create a copy of the whole group of files with timestamp of 20100201, bash command looks like this:
mv abc.4.0.20100204.body abc.4.0.20100201.body ...
Load output of external command to vim
In the directory open vim and load up list of files:
:r!ls *.*
The vim window will have the list of files displayed:
abc.4.0.20100204.body abc.4.0.20100204.header abc.4.0.20100204.seqnums abc.4.0.20100204.session ~ ~
This is read command :r followed by exclamation mark and command.
It executes the external command in shell and inserts its standard input into vim. In this case I want to get a list
of files but not the directory abc so I use:
ls *.*
Use regular expressions to prepare shell command
Now I want to generate copy commands for shell. In vim execute substitute command:
:%s/\(\(.*\)204\(.*\)\)$/cp \1 \2201\3/gc
You get asked if you want to execute each substitution, just press y, this is because of the c - confirm flag.
This is a substitute command:
<range>s/pattern/replace/options
To summarize it:
- Execute on the whole file - range
% - Substitute
s - Brackets are for remembering matched contents, they get numbered from left to right later referenced in replace
- Match anything up to 204 (part of time stamp in file name), I want to update the timestamp
- Match everything after the timestamp
- Replace the matched line with:
cp - Followed by the whole original line -
\1references the first bracket that matches everything up to end of the line in the original line. - Followed by the first part of filename up to
204- stored by second group of brackets and reference by\2in replace part - Followed by the string
201that replaces the original204string - Followed by the rest of the matched line -
\3 - Command flags:
g- global, execute the substitute command repeatedly on the line - not important here because I'm matching the whole linec- confirm before replacement
The vim window now looks like this:
cp abc.4.0.20100204.body abc.4.0.20100201.body cp abc.4.0.20100204.header abc.4.0.20100201.header cp abc.4.0.20100204.seqnums abc.4.0.20100201.seqnums cp abc.4.0.20100204.session abc.4.0.20100201.session ~ ~
Execute bash commands from vim
To execute bash commands in the current directory, first highlight the lines with Ctrl-v and down/up to highlight all commands. Now enter : to start typing the rest of the command. This will insert the range '<,'> signifying the highlighted lines. Type the rest of the command:
:'<,'>!bash
This executes commands in highlighted lines in bash. Quit vim and check the directory. You have copied files with 20100204 date stamp to the ones with 20100401:
> ls abc abc.4.0.20100201.header abc.4.0.20100201.session abc.4.0.20100204.header abc.4.0.20100204.session abc.4.0.20100201.body abc.4.0.20100201.seqnums abc.4.0.20100204.body abc.4.0.20100204.seqnums
I have loaded output of external bash command into vim, used vim's regular expressions to generate commands, then executed the commands in bash directly from vim.
No comments:
Post a Comment