## 17.18. Filtering Text Through a Unix Command

When you're editing in vi, you can 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.

In vi, you can filter text 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 couple of unusual features about how vi acts when you use this structure:

- First, 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.

- Second, 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.

- Third, 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 previous 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 message that you'd like to convert to all uppercase letters. ex has operators to convert case (Section 17.16), but it's also easy to convert case with the tr (Section 21.11) command. In this example, the second sentence is the block of text that will be filtered to the command:

>     One sentence before.
>     With a screen editor you can scroll the page
>     move the cursor, delete lines, insert characters,
>     and more, while seeing the results of your edits
>     as you make them.
>     One sentence after.

Keystrokes | Action | Results
--- | --- | ---
>     !)
> | An exclamation mark appears on the last line to prompt you for the Unix command. |
>     One sentence after.
>     ~
>     ~
>     ~
>     !_
>     tr '[a-z]' '[A-Z]'
> | Enter the Unix command, and press RETURN. The input is replaced by the output. |
>     One sentence before.
>     WITH A SCREEN EDITOR YOU CAN SCROLL THE PAGE
>     MOVE THE CURSOR, DELETE LINES, INSERT CHARACTERS,
>     AND MORE, WHILE seeING THE RESULTS OF YOUR EDITS
>     AS YOU MAKE THEM.
>     One sentence after.

To repeat the previous command, the syntax is as follows:

>     ! object !

It is sometimes useful to send sections of a coded document to nroff to be replaced by formatted output. 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.

> WARNING: Sometimes a filter-through on old, buggy versions of vi can completely scramble and trash your text. Things can be so bad that the u (undo) command won't work. If you've been burned this way before, you'll want to write your buffer (with `:w`) before filter-throughs. This doesn't seem to be a problem with modern versions, but be aware of it.

-- TOR

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