## 7.2. Executing UNIX Commands

You can display or read in the results of any UNIX command while you are editing in vi. An exclamation mark (`!`) tells ex to create a shell and to regard what follows as a UNIX command:

>     :!command

So if you are editing and you want to check the time or date without exiting vi, you can enter:

>     :!date

The time and date will appear on your screen; press RETURN to continue editing at the same place in your file.

If you want to give several UNIX commands in a row without returning to vi editing in between, you can create a shell with the ex command:

>     :sh

When you want to exit the shell and return to vi, press CTRL-D.

You can combine `:read` with a call to UNIX, to read the results of a UNIX command into your file. As a very simple example:

>     :r !date

will read in the system's date information into the text of your file. By preceding the `:r` command with a line address, you can read the result of the command in at any desired point in your file. By default, it will appear after the current line.

Suppose you are editing a file and want to read in four phone numbers from a file called phone, but in alphabetical order. phone reads:

>     Willing, Sue  333-4444
>       Walsh, Linda  555-6666
>       Quercia, Valerie  777-8888
>       Dougherty, Nancy  999-0000

The command:

>     :r !sort phone

reads in the contents of phone after they have been passed through the sort filter:

>     Dougherty, Nancy  999-0000
>       Quercia, Valerie  777-8888
>       Walsh, Linda  555-6666
>       Willing, Sue  333-4444

Suppose you are editing a file and want to insert text from another file in the directory, but you can't remember the new file's name. You could perform this task the long way: exit your file, give the `ls` command, note the correct filename, reenter your file, and search for your place.

Or you could do the task in fewer steps:

Keystrokes | Results
--- | ---
`:!ls` | Display a list of files in the current directory. Note the correct filename. Press RETURN to continue editing.
`:r newfile` | Read in the new file.

### 7.2.1. Filtering Text Through a Command

You can also send a block of text as standard input to a UNIX command. The output from this command replaces the block of text in the buffer. You can filter text through a command from either ex or vi. The main difference between the two methods is that you indicate the block of text with line addresses in ex and with text objects (movement commands) in vi.

### 7.2.1.1. Filtering text with ex

The first example demonstrates how to filter text with ex. Assume that the list of names in the preceding example, instead of being contained in a separate file called phone, is already contained in the current file on lines 96 through 99. You simply type the addresses of the lines you want to filter, followed by an exclamation mark and the UNIX command to be executed. For example, the command:

>     :96,99!sort

will pass lines 96 through 99 through the sort filter and replace those lines with the output of sort.

### 7.2.1.2. Filtering text with vi

In vi, text is filtered through a UNIX command by typing an exclamation mark followed by any of vi's movement keystrokes that indicate a block of text, and then by the UNIX command line to be executed. For example:

>     !)command

will pass the next sentence through command.

There are a few unusual features about how vi acts when you use this feature:

- The exclamation mark doesn't appear on your screen right away. When you type the keystroke(s) for the text object you want to filter, the exclamation mark appears at the bottom of the screen, but the character you type to reference the object does not.

- Text blocks must be more than one line, so you can use only the keystrokes that would move more than one line ( `G`, `{ }`, `( )`, `[[ ]]`, `+`, `-` ). To repeat the effect, a number may precede either the exclamation mark or the text object. (For example, both `!10+` and `10!+` would indicate the next ten lines.) Objects such as `w` do not work unless enough of them are specified so as to exceed a single line. You can also use a slash (`/`) followed by a pattern and a carriage return to specify the object. This takes the text up to the pattern as input to the command.

- Entire lines are affected. For example, if your cursor is in the middle of a line and you issue a command to go to the end of the next sentence, the entire lines containing the beginning and end of the sentence will be changed, not just the sentence itself.[30]

  > [30]Of course, there's always an exception. In this example, vim 5.0 changes only the current line.

- There is a special text object that can be used only with this command syntax: you can specify the current line by entering a second exclamation mark:

  >     !!command

  Remember that either the entire sequence or the text object can be preceded by a number to repeat the effect. For instance, to change lines 96 through 99 as in the above example, you could position the cursor on line 96 and enter either:

  >     4!!sort

  or:

  >     !4!sort

As another example, assume you have a portion of text in a file that you want to change from lowercase to uppercase letters. You could process that portion with the `tr` command to change the case. In this example, the second sentence is the block of text that will be filtered through the command.

Keystrokes | Results
--- | ---
`!)` | An exclamation mark appears on the last line to prompt you for the UNIX command. The `)` indicates that a sentence is the unit of text to be filtered.
`tr '[a-z]' '[A-Z]'` | Enter the UNIX command and press RETURN. The input is replaced by the output.

To repeat the previous command, the syntax is:

>     ! object !

It is sometimes useful to send sections of a coded document to nroff to be replaced by formatted output. (Or when editing electronic mail, you might use the fmt program to "beautify" your text before sending the message.) Remember that the "original" input is replaced by the output. Fortunately, if there is a mistake, such as an error message being sent instead of the expected output, you can undo the command and restore the lines.

Copyright © 2003 O'Reilly & Associates. All rights reserved.