jump to content

Satheesh Babu
2001/02/01

VI editor has an execute-in-shell mode which can be used with powerful UNIX tools to create neat filters.

Suppose you wish to process a part or all of the file you are editing in VI using the prowerful unix commands. Any command (or number of commands linked through pipes ) which takes stdin as input and outputs to stdout (most unix programs do have this option) can be made use of. In the normal VI mode (ie, you are NOT inserting, and not in : mode) type:

    !}your_command 

and press_return. You MUST NOT do a :!}your_command.

} is the motion command, which in this case is the next-paragraph. It can be j,k,l,h,G,w,$ etc (any single character motion command). You can add an argument where applicable, like for next 3 lines:

    !3jyour_command 

These characters are expanded to a range automatically. For example, G is equivalent to .,$ (current line to last line). So you can equivalently use : commands too.

Some Examples

You want to beautify the C program you are editing now:

    :1 (go to line 1) 
    !Gcb

You want to beautify one function:

    go to the beginning line of the function
    !}cb (assuming your next blank line comes only
      before the next function definition)

You want to beautify next 3 functions:

    !3}cb

Here is an example to show the use of : command

You want to convert all lower case characters to upper case in the lines 3 to 8:

    :3,8!tr  [a-z] [A-Z]

You also want to number these lines (illustrates use of pipe ):

    :3,8!tr [A-Z] | nl

Double space the next paragraph:

    !}sed G
Reverse next paragraph::

    !}sed 1\!G;h;$\!d or if you've tac,
    !}tac (if you don't've tac, you can simulate it with sed, from the shell -> sed 1!G;h;$!d )

Mail the previous 10 lines to a friend:

    !10kmailx -s "Hasta la vista baby" myfriend@wherever.com

Print with line numbering, next 20 lines:

    !20jnl|lp -dmyprintqueue -

Comment out the next function (you can do this easily in VI ,but just to illustrate:-):

    !}awk BEGIN{printf("/*\n");} {print;} END{printf("*/\n");}

Create a macro like this with BEGIN and END modified suitably (perhaps date, username etc ??) and you got a standardised comment structure!

Bottom line, if you want to process some file while editing, no need to save it, exit to the shell, process it and then back to VI.

References