12.  Vi Tutorial

In this tutorial, we describe some "advanced" vi concepts and commands, so you can appreciate the power of vi and so you decide how to build your knowledge of vi commands. Nearly all vi references list the available commands, but many don't bother to discuss how the commands interrelate; this topic is the main purpose of this tutorial.

12.1.  Cursor Movement Commands

The vi cursor movement commands allow you to position the cursor in the file and/or on the screen efficiently, with a minimum number of keystrokes. There are oodles of cursor movement commands - don't try memorizing them all at once! Later, we'll see that much of the power of vi comes from mixing cursor movement commands with other commands to delete, change, yank (copy), and filter text.

Please edit a large text file (say, wknight ) so you can experiment with each command as it is described. Keep in mind these commands will only work in Command Mode, not Insert Mode; if you start getting your "commands" in your text, press the ESC key to return to Command Mode.

  • cursor keys : As we've seen, cursor keys move by single character amounts left, down, up, and right. Movement above the top of the file, below the bottom, to the right of the end of a line, or left of the beginning is not allowed (no line wrapping).

  • hjkl : When vi was written (around 1978), many terminals on UNIX systems did not have cursor keys! h, j, k, and l were chosen as commands to move left, down, up, and right, respectively. Try them! Most vi diehards prefer these to the cursor keys because

    • (a) they are in the same place on all keyborads, and

    • (b) they fit nicely under the fingers, unlike most cursor keys, which are arranged in a box or "T" or some other nonlinear shape.

    Why h, j, k, and l? Well, in the ASCII character set, CTRL-H is backspace (moves left), CTRL-J is linefeed (moves down), and, of course, k and l are next to h and j, so you see, they're mnemonic.

  • 0 : ("zero", not "oh") Move to the beginning of current line. (To try this and the next few commands, use the cursor keys or h j k l to move to an indented text line that contains few "e" characters. If you can't find an indented line in your file, create one by inserting a few space characters at the beginning of a line.)

  • ^ : Move to first non-white character of current line. (For indented line, 0 and ^ are different.)

  • $ : Move to last character of current line.

  • tC : Move to (but not on) next character c in current line. (Press 0, then press te. This will move to the first e in the curent line.)

  • fC : Find (move on top of) next character c in current line. (Press fe, and the cursor will find - that is, move on top - the next e in the current line.)

  • TC : Move to (but not on) the previous character c in current line (Press $, then Te.)

  • FC : Find (move on top of) the previous character c in current line. (Press Fe.)

  • n| : Move to column n in current line. (Try 20 |. The digits 2 and 0 will not be displayed as you type them, but when you press | the cursor will move to column 20.) Try some experiments with t f T F | . When you do something illegal, vi will beep your terminal.

  • w : Forward to beginning of next "small" word ( a "small" word consists of unbroken alphanumeric characters or punctuation characters, but not mixed alphanumeric and punctuation). Try tapping w a dozen times or so - note what happens at punctuation.

  • W : Forward to beginning of next "big" word (alphanumeric and punctuation mixed). Try W a dozen times or so.

  • b : Backward to beginning of "small" word.

  • B : Backward to beginning of "big" word.

  • e : Forward to end of "small" word.

  • E : Forward to end of "big" word.

  • + Return : Move to first non-white space character on next line. (+ and the Return key have the same effect.)

  • - : Move to first non-white space character on previous line.

  • ) : Move to the end of sentence. (A sentence ends either at a blank line or at a period or examination mark followed by two space characters or at the end of a line. A period or exclamation mark followed by one space character does not end a sentence; this is correct behaviour, according to traditional rules of how sentences should appear in typed documents, but often appears wrong to those who have never suffered through a formal typing class.)

  • ( : Move to beginning of sentence.

  • } : Move to end of paragraph. (Paragraphs are seperated with blank lines, by vi 's definition.)

  • { : Move to beginning of paragraph.

  • H : Move to home position (top line) on the screen

  • M : Move to middle line on the screen.

  • L : Move to last line on the screen.

  • nG : Move to line n. If n is not given, move to the last line in the file. (Try 15G to move to line 15, for example. The CTRL-G command displays the name of the file, some status information, and the current line number. To move to the top of the file: 1G)

  • CTRL-d : Scroll down half-screen (see note).

  • CTRL-u : Scroll up half-screen (see note).

  • CTRL-f : Move forward one-screen (see note).

  • CTRL-b : Move backward one-screen (see note).

  • Note : These four scrolling/paging commands cannot be used with the delete, change, yank, or filter commands.

  • /reg_exp : Move to next occurrence of the regular expression reg_exp When you press /, the cursor drops to the lower left corner of the screen and waits for you to type in the regular expression. Press the Return key to finish; vi then searches forward for the next occurrence of the regular expression. For example, press /the followed by Return. This moves forward to the next occurrence of the, perhaps imbedded in the middle of some longer word (other, weather, etc.). If you just press / and then Return, vi searches for the next occurrence of whatever the last regular expression was that you searched for.

  • n : Has the same effect as pressing / and then Return; i.e., searches for the next occurrence of whatever the last regular expression was that you searched for.

  • ?reg_exp : Searches backward, rather than forward. If no reg_exp is given, it searches for the last regular expression that was entered. Both / and ? wrap around, so searching "below" the bottom or "above" the top of the file is legal.

  • N : Same as pressing ? and then Return.

12.2.  Repeat Counts

Many of the movement commands discussed above can be preceded with a repeat count; the movement is simply repeated the given number of times:

  • 3w : Move forward three words

  • 5k : Move up four characters

  • 3fa : Find the third succeeding a in current line

  • 6+ : Move down six lines

For some commands, the "repeat counts" has special meaning:

  • 4H : Move to Line 4 on the screen (home plus 3)

  • 8L : Move to the eigth line from the bottom of the screen

  • 3$ : Move to the end of the third line down

For some commands (e.g., ^) the repeat count is ignored; for others (e.g., / and ? ) it is illegal

12.3.  Deleting Text

We've seen that dd deletes the current line. This can be used with a repeat count: 3dd deletes three lines, the current line, and the two following lines.

The d command can be used as a "prefix" on most of the movement commands above to delete nearly arbitrary chunks of text. When used with d, the movement commands are called target specifiers. d can be given a repeat count. (As you try these experiments, remember to press u after each command to undo the deletion).

  • dw : Delete "small" word forward

  • d3w : Delete three "small" words forward

  • 3dw : Three times, delete "small" word forward

  • 3d3w : Three times, delete three "small" words forward (that is, delete nine "small" words forward)

  • d+ : Delete current line and next line down

  • d/the : Delete from current character up to but not including the next occurrence of the pattern the.

  • d$ : Delete to end of line

  • d0 : Delete to beginning of line

  • d30G : Delete from the curent line to and including Line 30

  • dG : Delete from current line to and including last line

  • d1G : Delete from current line to and including Line 1

To delete single characters, use x. x can be given a repeat count:

  • 15x : Delete current and 14 following characters

x is actually just an abbreviation of d1; that is, delete one character right.

12.4.  Changing Text

The c command is similar to d, except it toggles vi into Insert Mode, allowing the original (unwanted) text to be changed to something else.

For example, put the cursor on the beginning of a word (press w to get to the beginning of the next word). Then, press cw to change that word. On the screen, the last character in the word being changed will be replaced with a $ symbol indicating the boundary of the change; type in a new word (you will overwrite the original word on the screen) and press the ESC key when done. Your input may be longer or shorter than the word being changed.

Put the cursor at the beginning of a line containing at least three words, and try c3w to change three words. Try c$ to change to the end of the current line. In all cases where the change affects only the current line, the boundary of the change is indicated with $.

When a change affects more than just the current line, vi deletes the original text from the screen and toggles into Insert Mode. For example, try c3+ to change the current and the next three lines; vi deletes the four original lines from the screen and toggles into Insert Mode in a new blank line. As usual, press the ESC key when you have finished entering your new text.

Some other change commands:

  • cc : Change current line

  • 5cc : Change five lines (current and next four)

  • c/the : Change from current character up to but not including the next occurrence of the pattern the

  • c$ : Change to end of line

  • c30G : Change from the current line to and including Line 30

  • cG : Change from curernt line to and including last line

  • c1G : Change from curernt line to and including Line 1

12.5.  Yanking (Copying) Text

The y command yanks a copy of text into a buffer; the yanked text can then be put (or pasted) elsewhere in the file using p or P.

The simplest form of yank is yy to yank the current line; after yy, try p to put a copy of the yanked line after the cursor. Following yy, you can make as many copies of the yanked line as you want by moving up and down in the file and pressing p.

To copy multiple lines, try, for example, 5yy (yank the current and next four lines). p puts a copy of the yanked lines after the cursor; the sequence 5yyp "works" but it probably doesn't do what you would like. The P command is like p, but puts a copy of the yanked text ahead of the cursor; try the sequence 5yyP.

Other yank commands:

  • y3w : Yank three words

  • y$ : Yank to end of current line

  • y1G : Yank from current line to and including Line 1

12.6.  Filtering text

The filter command ! , prompts for the name of a UNIX command (which should be a filter), then passes selected lines through the filter, replacing those selected line in the vi buffer with the output of the filter command. vi 's ability to pass nearly arbitrary chunks of text through any UNIX filter adds incredible flexibility to vi , at no "additional cost" in size or performance to vi itself.

Some examples will help illustrate. Create a line in your file containing just the word who and absolutely no other text. Put the cursor on this line, and press !! This command is analogous to dd, cc, or yy, but instead of deleting, changing, or yanking the current line, it filters the current line. When you press the second !, the cursor drops down to the lower left corner of the screen and a single ! is displayed, prompting you to enter the name of a filter. As the filter name, type sh and press the Return key. sh (the Bourne shell) is a filter! It reads standard input, does some processing of its input (that is, executes commands), and sends its output (the output of those commands) to standard output. Filtering the line containing who through sh causes the line containing who to be replaced with a list of the current users on the system - right in your file!

Try repeating this process with date . That is, create a line containing nothing but the word date , then put the cursor on the line, and press !!sh and the Return key. The line containing date is replaced with the output of the date command.

Put your cursor on the first line of the output of who. Count the number of lines. Suppose, for example, the number is six. Then select those six lines to be filtered through sort; press 6!!sort and the Return key. The six lines will be passed through sort, and sort's output replaces the original six lines.

The filter command can only be used on complete lines, not on characters or words.

Some other filter commands (here, < CR > means press Return):

  • !/the < CR > sort < CR > : Sort from the current line up to and including the next line containing the

  • !1Ggrep the < CR > : Replace from the current line to and including Line 1 with just the lines that contain the

  • !Gawk '{print $1}' < CR > : From the current line to the end of file, replace every line with just its first word.

12.7.  Marking Lines and Characters

You can mark lines and characters to be used as targest for movement, deletion, change, yanking, and filtering using the command mc, where c is a lowercase letter.

For example, put the cursor in the middle of some word and press ma. This marks the character under the cursor as mark a.

Now, move the cursor off the marked character and to a different line ( use the cursor keys, CTRL-u, or whatever). To return to the marked line, press 'a (that is, single quote, then a). This moves to the first non-white space character on the line containing mark a.

Move off that line again. To return to the marked character, press `a (that is, backquote, then a). This moves on top of the character marked with a.

Marking is usually used with deleting, changing, yanking or filtering. For example, move the cursor to a line other than the one containing mark a, and then press d'a (d, single quote, a). This deletes from the current line to and including the line marked with a.

Put the cursor in the middle of a different word and press mb to set mark b. Now, move the cursor away from that word (but only a few lines, so you can see what we're about to do more easily), and then press d`b (d, backquote, b). This deletes from the current CHARACTER to and including the CHARACTER marked with b.

As another example, to sort the output of who, mark the first line (ma), then move the cursor to the last line and press !'asort and the Return key.

If you jump to a mark and decide you want to jump back to whatever you jumped from, you can press '' (jump back to line) or `` (jump back to character).

12.8.  Naming Buffers

When you delete, change, or yank text, the original text is stored (until the next delete, change, or yank) in an unnamed buffer from which it can be put using p or P. Using the unnamed buffer, only the most recently deleted, changed or yanked text may be recovered.

If you wish to delete, change, or yank multiple sections of text and remember them all (up to a maximum of 26), you can give a buffer name ahead of the delete change or yank command. A buffer name has the form "c (double quote, lowercase c).

For example, press "ayy to yank the current line into buffer a, then move to a different line and press "byy to yank that line into buffer b. Now, move elsewhere in the file and press "ap and "bp to put copies of the text stored in buffers a and b.

Some other named buffer commands:

  • "a6yy : Yank six lines (current and next five) into buffer a

  • "bd1G : Delete from the curernt line to and including Line 1, storing the deleted lines in buffer b

  • "cy'c : Yank from the current line to the line marked c into buffer c (marks and buffers are distinct, and may have the same name without confusing vi )

12.9.  Substitutions

To substitute one chunk of text for another in lines throughout your file, use the :s command. Some substitute examples:

  • :1,$s/the/THE/g From Line 1 to the last line (line $), substitute for the text THE; do this globally in each line where the occurrs

  • :'a,.s/.*/ha ha/ From the line marked a to the current line (line .), substitute for everything on the line the text ha ha

12.10.  Miscellaneous "Colon Commands"

All colon commands begin with a colon; when you press the colon, the cursor drops to the lower left corner of the screen, and a colon prompt is displayed waiting for you to finish your colon command.

Some important examples:

  • :w Write the buffer contents to the file without quitting from vi

  • :w abc Write the buffer contents to the file abc (creating abc if it doesn't exist, or overwriting current contents if it does exist) without quitting from vi

  • :1,10w abc Write lines 1 through 10 to file abc

  • :'a,$w abc Write from the line marked a to the last line into file abc

  • :e abc Edit file abc, instead of the current file. vi prints an error message if changes have been made to the curernt file that have not been saved with :w

  • :e! abc Edit file abc, throwing away any changes that may have been made to the current file

  • :e # Edit the prior file edited (successive :e# commands toggle back and forth between two files)

  • :f abc Change the file anme for the current vi buffer to abc

  • :q Quit, unless unsaved chanegs have been made

  • :q! Quit, throwing away any changes that may have been made

  • :r abc Read the file abc into current vi buffer, after the line the cursor is on (try :r croc to read in a copy of the croc file)

  • :!cmd Execute command cmd (who, sort, ls, etc.)

12.11.  Setting Options

Various options affect the "feel" of vi . You can display all the various options that can be set using the colon command :set all. You can also use set to change options.

For example, if you want to see line numbers for the lines in the file you're editing, use the command :set number. To turn off line numbering, use the command :set nonumber. Most options can be abbreviated; :set nu turns on line numbering and :set nonu turns off line numbering.

If you :set nomagic, the special meanings of regular expression characters (period, asterisk, square bracket, etc.) are switched off. Use :set magic to restore the special meanings.

Some options take a value. For example, :set tabstop=4 causes tabs to be displayed as four space characters, rather than the usual eight.

If you find you always want certain options set certain ways, you can put the set commands you want ina file .exrc, or you can set up the environment variable EXINIT to specify the options you want.

For example, if your login shell is Bourne shell, this line could go in your .profile file:

	EXINIT='set nomagic nu tabstop=4'; export EXINIT

If your login shell is a C shell, this line could go in your .login file:

	setenv EXINIT 'set nomagic nu tabstop=4'

12.12.  Key Mappings

If you find you're performing a series of simple commands over and over, you can map the command series to an unused command key using the :map command. If your mapping must include control characters such as Return key (CTRL-M in ASCII) or the ESC (CTRL-[ in ASCII) key, precede such characters with CTRL-v to suppress their usual special meaning.

For example, this command maps CTRL-A to move the cursor forward 55 lines, then back up to the most recent blank line, then change that blank line to a formfeed (CTRL-L) and three blank lines. That is, each CTRL-A will paginate the next page, without splitting paragraphs across pages.

Note: In this command, each control character is shown as ^C, where C is some uppercase letter. For example, CTRL-M is shown as ^M. Also, when you enter this command you will not see the CTRL-v characters as shown: each CTRL-v merely suppresses the usual special meaning of the following control character, so when you press the sequence ^V^M, all you will see on the screen is ^M. In this command, ^M is the Return key and ^[ is the ESC key.

	:map ^A  55+?^$^V^Mcc^V^L^V^M^V^M^V^M^V^[

12.13.  Editing Multiple Files

You can edit multiple files with vi by giving multiple file names as command line arguments:

	vi croc fatherw  wknight

Three colon commands are used to move through the multiple files:

  • :n Move to the next file in the argument list (you must save changes with :w or vi will print an error message)

  • :N Move to the previous file in the argument list (you must save changes with :w or vi will print an error message)

  • :rew Rewind and start over with the first file in the argument list

The :n, :N, and :rew commands are somewhat clumsy, but there are some important benefits: the contents of named buffers ("a, "b, "c, etc.) are remembered across files, so you can use :n and :rew with p and P to copy text back and forth between files. Also, the most recent search string for the / and ? commands remembered across files, so you can do repetitive searches in multiple files rather easily.

For example, try the following experiment: First get out of vi , then execute vi with croc and wknight as arguments:

	$ vi croc wknight

In croc, search for the

/the < CR >

Yank this line into buffer a:

"ayy

Now go to the next file (you've made no change to croc, so this will work):

:n < CR >

Search for the "next" line containing the, without retyping the search string:

n

Put a copy of buffer a after the current line in wknight:

"ap

Move down two lines, and yank the current line into buffer b:

jj"byy

Save the changes to wknight

:w < CR >

Now, rewind to croc

:rew < CR >

Search again, and put a copy of buffer b after the found line:

n"bp

Save the changes, and exit vi

ZZ

12.14.  Final Remarks

This tutorial was intended to introduce some of the vi capabilities that you might overlook in your system's vi manual or that might not be mentioned in the manual (different systems have manuals of widely varying quality).

You will not be a vi expert after reading this tutorial, but you will have a good appreciation of vi 's capabilities. Only time and effort can make a vi expert. But the efficiency and universality of vi make this effort pay off in the long run.

You may have decided you hate vi . So be it! But be aware that vi remains the standard UNIX text editor - the one editor you can count on being available on every UNIX system you'll use - so even if you prefer to use something else day-to-day, you'd be well advised to know the bare minimum vi material covered in this tutorial.