Command Output in vi
It often happens that we want the output of UNIX
commands in the file we are editing. The sledgehammer approach is to run the command and redirect it to
a file, then edit that file. If that file containing the commands output already exists, we can use the :r from
ex-mode to read it in. But, what if it doesn't yet exist. For example, I often want the date in text
files as a log of when I input things. This is done with a combination of the :r (for read) from ex-mode and
A shell-escape is when we start from one program and jump out of it (escape) to a shell.
Our original program is still running, but we are now working in a shell that is a child process
of that program.
To do a shell-escape, we need to be in ex-mode. Next, press the exclamation mark (!) followed by
the command. For example, to see what time it is, type :!date. We then get the date at the bottom of the
screen with the message to press any key to continue. Note that this didn't change our original text; it just
showed us the output of the date command.
To read in a command's output, we need to include the :r command, as in :r!date. Now, the output of the
date is read into the file (it is inserted into the file). We could also have the output replace the current
line by pressing ! twice, as in !!date. Note that we are brought down to the last line on the screen, where there
is a single !.
If we want, we can also read in other commands. What is happening is that vi is seeing the output of the
command as a file. Remember that :r <file_name> will read a file into the one we are editing. Why not read
from the output of a file? With pipes and redirection,
can be files.
We can also take this one step further. Imagine that we are editing a file containing a long list. We know that
many lines are duplicated and we also want the list sorted. We could do :%!sort, which, if we remember from our
earlier discussion, is a special symbol meaning all the lines in the file. These are then sent through the command
on the other side of the !. Now we can type
to remove all the duplicate lines.
Remember that this is a shell-escape. From the shell,
we can combine multiple commands using pipes. We can do it here as well. So to save time, we could enter
:%!sort | uniq
which would sort all the lines and remove all duplicate lines. If we only wanted to sort a set of lines, we
could do it like this
which would sort lines 45 through 112. We can take this one step further by either writing lines 45-112 to
a new file with :45,112w file_name or reading in a whole file to replace lines 45-112 with :45,112r file_name.