TOC BACK FORWARD HOME

UNIX Unleashed, Internet Edition

- 3 -

Text Editing with vi and Emacs

by Jeffrey A. Simon

A text editor is one of the most common and useful tools to be found in any computer system. It is a program that is used to create and modify text or other data-type objects, usually interactively by the user at a terminal. It is distinguished from a word processor or desktop publishing program in that a text editor is generally expected to produce plain ASCII text files that do not have embedded formatting information. The latter programs are intended to produce more complex documents that contain much more formatting information. For example, a typical word processor has a graphical user interface and is capable of producing "what-you-see-is-what-you-get" printed output.

Common uses of a text editor are to produce simple ASCII text files, program source code, e-mail, and so on. Therefore, text editors are often extended to provide features that assist with specific aspects of such tasks, such as the formatting of a specific programming language. For example, such extended modes exist for C++, Lisp, and HTML, to name only a few. Detailed examples of some of these features will be described later in this chapter.

This chapter will examine two of the most popular and widely used editors in the UNIX world, vi and Emacs. In addition to being useful tools, each of these editors has its own group of devoted users, ready to "sing praises" to the virtues of using their favorites. In any case, you can get a lot of work done with either of these tools.

Full-Screen Editors Versus Line Editors

A full-screen editor is one that displays on the user's terminal a view of all or a portion of the document he or she is working on. For example, on a 25-line display, the user sees a 24-line section of the document. When using an editor, you are not actually making edits to the file that is stored on the hard disk. What happens is that when the editor is commanded to begin working with a particular file, a working copy of that file is made. This working copy is often called the buffer. Adding, changing, and deleting of text ("editing") is done only within the buffer until the file is saved. You often hear the advice to "save your work." This advice is applicable to using a full-screen editor as well as any other computer work that uses a buffer in the same way.

You can think of the screen as a movable viewport into the buffer. This viewport is also often called a window. Editing actions take place at or relative to a specific point on the screen referred to as the cursor. The cursor is usually indicated on the screen by some sort of highlighting, such as a underscore or a solid block, which may or may not be blinking. Edits to the buffer are shown on the screen as soon as they are entered. This type of user-interface makes simple editing functions very convenient for the user.

In contrast, a line editor is one that does not attempt to show the appearance of a continuous section of the document being edited. It concentrates on editing one line at a time. Thus, its user interface is more primitive. The type of editing that you would naturally do in a full-screen editor becomes more cumbersome under such an arrangement.

However, you should not be misled into thinking that the primitive user interface of the line editor means that a line editor lacks power or that all line editors are obsolete. (A great many line editors are obsolete; the trick is in recognizing those that are not!)

There are certain very powerful editing functions that are most easily executed by using a line editor. As an example, if you had to reverse the order of the lines in a file, you could do that with eight keystrokes in vi! So it might be a good thing if there was an editor that could take advantage of the power of both the full-screen and line-oriented modes.

What Is vi?

vi (usually pronounced vee-eye) is a full-screen text editor that comes with nearly every UNIX system. Many versions of vi or very similar programs have been made for other operating systems. Such versions exist for Amiga, Atari, Macintosh, MS-DOS, OS/2, Windows 3.1/95/NT, and probably more.

The Relationship of vi and ex

vi is "closely" related to the line editor ex. (In fact, they are one and the same!) vi is the visual (or open) mode of ex. This means that you could start editing a file with the ex editor. At any time, you can invoke the visual mode of ex. Voile--you are in vi! From vi you can at any time "drop down into ex" because all ex commands are available from within vi. Thus you can easily go back and forth between the visual and line-oriented modes, executing the particular editing operation you need from the mode in which it is most effectively accomplished. Later on in this chapter, you will see examples of such operations.

Why Would I Be Interested in Using vi?

Many computer users are familiar with the powerful word processing programs available widely on personal computers. If you are used to such a tool, you may be disappointed to find out the vi is not a "what-you-see-is-what-you-get" or WYSIWYG (pronounced wissy-wig) word processor. However, it is rare that such a word processing program is available on the typical UNIX system. vi on the other hand is nearly always available. One of the strongest reasons for knowing at least the rudiments of vi is the fact that it is nearly always available on any UNIX system. It becomes particularly invaluable to those who have to periodically go into a UNIX environment away from their everyday system.

While the lack of a graphical user interface might be a hindrance to the novice, many "power users" believe that the fastest and most productive interaction with online tools is through command-based interfaces. This is also true of vi. Once the keystrokes of the commands become second nature, the productivity of a vi user is not easily surpassed. In fact, the apprehension of the uninitiated toward command-based interfaces is probably due to the following common misconception: People think they have to memorized an obtuse, counter-intuitive set of command keys when, in fact, it is more a matter of finger training than memorization.

For example, suppose you want to move the cursor (the point where actions on the text take place) down one line. After learning to use vi and becoming comfortable with it, there is no mental process (such as "Move down--let's see that's a "j"). Rather it is a physical motion (such as "Move down--finger motion to press the "j" key). Think of it as like learning to drive a car. After having mastered the process, if you see a ball bouncing into the road ahead, you do not have a mental process (such as "Ball--child--STOP!--Let's see, which pedal is it? Where's the instruction manual?!). Rather, your body reacts instantly to press the brake pedal. It is the same way with a command-based interface. After you learn it, it is your fingers that effectively execute the command.

Starting Up and Exiting vi

The first thing to learn with any new program is how to start it and how to get out of it! The simplest way to start vi is to type its name along with the name of the file you wish to edit. If no name is specified, vi responds with an empty screen, except for a column of tildes along the left side. Your screen looks similar to the following:

~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
Empty buffer

At the bottom of the screen there may be nothing at all (yet another example of the terseness of UNIX!), or "Empty buffer," depending upon your version of vi. The tildes (which is the name of the "squiggly-line" character) indicate that the line is empty. There are as many tildes as needed to fill your monitor's screen, leaving one line at the bottom which is used to display status information (as shown in the previous example), or to enter commands. In this chapter, the line at the bottom of the screen will be referred to as the command line.

If you entered a file name, the first lines of that file are displayed until the screen is full. If there are not enough lines to fill the screen, once again, tildes are displayed on the empty lines. In addition, the name of the file and the number of lines are displayed at the bottom of the screen. For example, your screen may look like the following example of a vi screen after loading a text file. (The reader may recognize this text as taken from Sun Tzu, The Art of War.)

    If wise, a commander is able to recognize changing circumstances and to
act expediently.  If sincere, his men will have no doubt of the certainty of
rewards and punishments.  If humane, he loves mankind, sympathizes with others,
and appreciates their industry and toil.  If courageous, he gains victory by
seizing opportunity without hesitation.  If strict, his troops are disciplined
because they are in awe of him and are afraid of punishment.
    Shen Pao-hsu ... said: 'If a general is not courageous he will be unable
to conquer doubts or to create great plans.'
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
"art1"  8 lines, 576 characters

The second most important thing to know about operating a program is how to get out of it! There are several useful ways to get out of vi, depending upon what you want to do with your buffer. All of them must be executed from command mode (described later in this chapter), so to be sure you are in command mode, press the Esc (for Escape) key until you hear a beep before trying the following commands while you are learning.

Entering the command ZZ will save your file and exit. The other ways of exiting involve ex mode commands. To enter ex mode, enter the colon character ":". The screen display will change so that a colon is displayed on the bottom line of the screen and the cursor will be positioned immediately to the right of this colon, waiting for your command.

The q key will "quit" the file, if no changes have been made since the last save of the file. If a change has been made, you will be prevented from exiting and the following warning will be displayed: No write since last change (use ! to override). The command wq can be used to handle this situation, by writing the file before exiting. Or you can go ahead and use the q! as the message indicates, to go ahead and quit anyway, abandoning all of your edits since the last save of the file. (It's good to keep in mind the :q! command for those cases in which you have truly messed up and want to get rid of your mess!)

Table 3.1 summarizes the exiting commands presented so far.

Table 3.1. Exiting commands.

Keystrokes Result
ZZ Save file and immediately exit
:wq Save file and immediately exit (same as ZZ)
:q Exit; prevented if file not saved
:q! Exit; forced exit whether saved or not

Getting Started: The Big Picture

Let's look at some of the pieces of the big picture that give vi its character.

vi Has Modes

vi was created back when the keyboard and screen method of interaction with computers was new. In those primitive days, keyboards did not have all of the useful function keys that are now familiar. Therefore, vi was designed to allow you to enter and modify text using only the typewriter keys plus the escape key. (Nowadays other key sequences are sometimes recognized, such as the cursor control keys.)

Although it may seem like a limitation to not take advantage of the many additional keys available on the modern keyboard, the "silver lining" of this limitation is that all functions can be executed without taking your hands away from the touch-typing position. The result makes for efficient and rapid typing.

To enable the many editing functions necessary for interactive, full-screen editing, vi is operated in three modes. The insert mode is used for entering text. While in insert mode, every typewriter key pressed is displayed on the screen and entered into your text. The command mode is used for most editing functions. While in command mode, nearly every typewriter key pressed will cause some action other than the direct entry of text, such as moving around to different points in your text, deleting blocks of text, copying blocks of text, and so on. A third mode, called ex mode is used to execute additional functions, such as searching, global replacement, manipulation of multiple file, and many more. The ex mode is based on the underlying ex editor and will be described in greater detail later in the section "Using the Power of ex from vi."

Starting vi

When vi is started up, the default mode is command mode. Test this out: start vi by typing in the program name only:

$ vi

You will see something similar to the following:

~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
Empty buffer

i--Insert

Now press the "i" key to enter insert mode. The "i" character will not echo (that is, it will not be displayed on your screen). Thereafter, every key you press will be displayed as it is entered into the buffer. Now begin to enter some text. Let's assume you are entering some text from The Art of War by Sun Tzu, and that the passage you have selected results in your screen looking as follows. Note that the cursor position is indicated in the example by an underscore under the period at the very end of the passage:

    If wise, a commander is able to recognize changing circumstances and to
act expediently.  If sincere, his men will have no doubt of the certainty of
rewards and punishments.  If humane, he loves mankind, sympathizes with others,
and appreciates their industry and toil.  If courageous, he gains victory by
seizing opportunity without hesitation.  If strict, his troops are disciplined
because they are in awe of him and are afraid of punishment.
    Shen Pao-hsu ... said: 'If a general is not courageous he will be unable
to conquer doubts or to create great plans.'
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~

Esc--Cancel

When you have entered enough, press the Esc key to return to command mode. (If you are already in command mode when you press Esc, you will hear a beep.) The Esc key is used to cancel an incomplete command as well as to terminate any type of insert mode. After pressing Esc, the cursor backs up over the last character you typed. Leave it there for now.

Unfortunately, there is no readily visible indication of which mode you are in. However, it is pretty easy to see what mode you are in. If the keystrokes go into the text, you are in insert mode; if your screen jumps around wildly, beeps, and all kinds of weird things are happening, either you are asleep and having a vi nightmare, or you are most definitely in command mode. If you are unsure of what mode you are in, just press Esc twice to get the beep confirming that you are in command mode. (Be sure to pinch yourself first to make sure you are awake!)

Moving Around and Simple Editing

It's time to look at the most basic movement commands, the ones that you must train your fingers to execute automatically.

The Most Important Movement Keys

Editing commands in vi are composed of objects and commands. Objects are used by themselves to move around, or "navigate," in the buffer. A single object keystroke either causes the cursor position to move on the screen, or to reposition the "viewport" in the buffer. Let's see how the various movement commands affect the cursor position in our sample text.

hh--Cursor Left

First, move the cursor back five positions by pressing the h key five times (if you see five h's go into the text, you forgot to press the Esc key). The cursor should now be under the "p" of "plans" (see the following example):

    If wise, a commander is able to recognize changing circumstances and to
act expediently.  If sincere, his men will have no doubt of the certainty of
rewards and punishments.  If humane, he loves mankind, sympathizes with others,
and appreciates their industry and toil.  If courageous, he gains victory by
seizing opportunity without hesitation.  If strict, his troops are disciplined
because they are in awe of him and are afraid of punishment.
    Shen Pao-hsu ... said: 'If a general is not courageous he will be unable
to conquer doubts or to create great plans.'
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~

kk--Cursor Up

Now let's move the cursor up five lines using the k key. As you might expect, there is a shortcut for pressing the key five times. And you would be right. Just prefix the object (or action) portion of the command with a number. Instead of pressing the k key five times, you would have the same result by typing 5k. Try this now. The cursor should now be under the "e" of "he" (see the following example):

    If wise, a commander is able to recognize changing circumstances and to
act expediently.  If sincere, his men will have no doubt of the certainty of
rewards and punishments.  If humane, he loves mankind, sympathizes with others,
and appreciates their industry and toil.  If courageous, he gains victory by
seizing opportunity without hesitation.  If strict, his troops are disciplined
because they are in awe of him and are afraid of punishment.
    Shen Pao-hsu ... said: 'If a general is not courageous he will be unable
to conquer doubts or to create great plans.'
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~

There is a limit to the effect of the object you can use. For example, if the h or l keys are used with an object that would go beyond either the beginning or the end of the line the cursor is on, the cursor stays at the beginning or end of the line and the beep will sound.

There are other commands that work like the h and k keys. Their functions are described in Table 3.2. The best way to get used to how they work is to practice using them. The most frequently used movement keys are as shown in Table 3.2.

Table 3.2. Frequently used movement keys.

Keystroke(s) Moves
h one character left
j one line down
k one line up
l one character right
w, W one word forward (W ignores punctuation)
b, B one word backward (B ignores punctuation)
$ to end of line
^ to first non-space character of line
0 to beginning of line
G to top of buffer
nG where n is a whole number, to line n

The upper- and lowercase versions of the word movement commands have a subtle difference. The lowercase version counts most punctuation marks as "words." The uppercase version skips over them as if they were not present.

You should practice moving around in your sample text, using the previously described commands. Although they may seem awkward at first, you will soon get used to them as your fingers are trained.

The Most Important Editing Procedures

Let's look at some of the simplest and most often used editing procedures:

Changing Text Nobody's perfect. So you will sooner or later want to change some text that you have created. In fact, more text editing time is probably spent modifying existing text than in entering brand new text. So you will need some easy ways of changing text. This section shows how.

x--Delete Character The simplest way to delete text is with the x command. This command causes the character that the cursor is over to be deleted, and the remaining characters on the line to be shifted one character to the left. You can think of "x-ing" out the text you want to get rid of. If the character deleted is the last one on the line, the cursor moves one character to the left, so as not to be over non-existent text. If there is no more text on the line, the beep will sound.

d--Delete Object The delete command requires a text object on which to operate. A text object, or object for short, is the block of text that would be traversed by the use of a movement command. For example, w will advance to the next word. So dw will delete to the beginning of the next word. 5w will advance to the beginning of the fifth word (remember, punctuation symbols count as "words" to the w command). So 5dw (or alternatively d5w) will delete to the beginning of the fifth word. Both forms work because 5dw mean "do five delete-words;" d5w means "do delete five words."

dd--Line Delete One of the most often used forms of the d command is the special version, dd, which will delete an entire line. As before, 5dd would delete five lines.

D--Big Delete The uppercase form D is used to delete from the cursor position to the end of the line. It has the same action as d$.

u--Undo After learning how to do deletes, the first thing I want to know is whether there is an undo function! There is. It is invoked naturally by the u command. The u command will undo the most recent change to the file (not only deletes, but any edits). The cursor does not need to be at the location of that most recent change. Unfortunately, standard vi has only one level of undo. Once a second change is made, you cannot undo the first. If you press u a second time, it will "undo the undo," which is sometimes known as "redo." Repeated presses of the u key will toggle the text back and forth between the two versions.

U--Big Undo The "big brother" of the u command, the U command will undo all changes made to the line that the cursor is on, since the cursor was last moved on to that line. After the cursor is moved off of a line, the U command will no longer work on the edits that have already been made to that line.

.--Repeat Repeats the last editing command.

How Commands Are Formed By now you have probably noticed that there is a pattern to the structure of the vi commands. Firstly, the commands are (somewhat) mnemonic, which means that the letter of the command should remind you of the function being executed. Secondly, many commands have an uppercase version, which are usually a modified form the basic, lowercase form. Thirdly, all commands can be multiplied by a repeat count, entered as a prefix.

The easiest ways to see how the commands are formed is shown in Table 3.3. You can see that there are several ways of combining command elements to get the result you want. To repeat a command, just enter the repeat count prior to the command itself, as in the previous examples of cursor motion and deletion.

Table 3.3. How vi commands are formed.

General Form of vi Commands
{count}{command}{object} All parts are optional (see the following).
The {count}, if present, causes the command to be executed count number of times.
The {command}, if present, causes some action to take place. If absent, the cursor is moved according to the object.
The {object} is used together with the command to indicate what portion of the text is to be affected.
Specific Forms of vi Commands
{count} Position the cursor count lines down, if terminated with return or +; position the cursor count line up if terminated with -.
{command} Execute the command.
{object} Move the cursor over the indicated block.
{count}{command} Execute the command count times.
{count}{object} Move the cursor over count indicated blocks.
{command}{object} Execute the command over the indicated block.

Some examples of combining some of the commands that you already know are shown in Table 3.4.

Table 3.4. Examples of combining commands.

Command Result
h Move cursor left one character
3h Move cursor left three characters
dd Delete one line
3dd Delete three lines
w Move cursor forward one word
dw Delete one word
3dw Delete three words

You now have the basic editing commands that will enable you to get started. You might wish to start practicing right away with these few commands. With these commands you would be able to do any text editing project. But you wouldn't want to. By adding some additional commands, you can make your work much faster and easier. The whole point of computers is to make work easier, so why not use the power of vi to have the computer do what it is good at!

Other Useful Editing Commands a--Append The a command is used to append text. It is almost identical to the i command. The slight difference is that the i command inserts text at the cursor position; the a command appends text immediately after the cursor position. To illustrate the difference, we will use both commands to insert the phrase "is able to" into the sample text. For example, suppose your screen looks like the following example, with the cursor at the "r" of "recognize" (we want to insert the missing phrase "is able to" between the words "commander" and "recognize" ):

If wise, a commander recognize changing
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~

Type the following to use the i command to insert text:

iis able to Esc

(There is a blank between the word "to" and the Esc key.) Your screen should look like this after inserting "is able to":

    If wise, a commander is able to_recognize changing
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~

Now restore the text to the way it was by executing an undo command. Press the u key. (If a "u" is inserted into your text, you forgot to press Esc after the first insert.) Now before trying the a command, move the cursor back one character with the h key. Your screen should now look like the following:

     If wise, a commander_recognize changing
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~

Type the following:

ais able to Esc

As you can see, the action of the i and a commands differ by where the insertion begins.

A--Big Append Like the a command, but begins the append at the end of the line.

TIP: You can insert a repeated string sequence by using one of the insert or append commands with a repeat count. For example, to insert 78 asterisk characters you could type 78i*Esc.

c--Change Object To change text, you can use the c command. The c command takes an object to indicate the block of text that will be changed. The c command works like the d command followed by the i command. That is, it first performs the deletion that would be performed by the d command with the same object, then allows the insert of any amount of text (including line feeds) until the Esc key is pressed. This behavior makes it especially useful in such situations where you want to change the text from the position of the cursor to the beginning of the line (using c0) or to the end of the line (using c$).

cc--Change Line In a similar vein, the cc command works like the dd command followed by an i command. It deletes the line the cursor is on and then inserts all keystrokes typed until the Esc key is pressed.

C--Big Change The C command works like the D command followed by the i command; it deletes the text from the cursor position to the end of the line; then enters insert mode. The C command has the same action as c$.

r--Replace Character The r command will replace the single character where the cursor is placed. After the r key is pressed, no change is seen on the screen. The next key typed will replace the character at the cursor position, and then vi returns to command mode. It is a simple way to change just one character.

When used with a numeric count, the same replacement occurs over count characters. For example, suppose the screen looks like the following, with the cursor under the "c" of "commander":

If wise, a commander recognize changing
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~

Now suppose you type 4rx. The screen will now look like the following, and vi will be in command mode. Note that the cursor has moved to the end of the replaced text:

     If wise, a xxxxander is able to recognize changing
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~

R--Big Replace The uppercase version of the r command differs from the r command by the same pattern that the uppercase version of the d command and the c command differ from their lowercase versions. The R command allows the replacement of the text from the cursor position to the end of the line. Any text entered after typing R until the Esc key is pressed will overlay the existing text on the screen, up to the end of the line. Thereafter, text entered will be appended to the end of the line.

When used with a numeric count, the same replacement occurs count times. This use of the R command may not produce what you are expecting.

o--Open Line The o command opens up a new line below the line the cursor is on and goes into insert mode.

O--Big Open Line The O command opens up a new line above the line the cursor is on and goes into insert mode.

A Copy Is a "Yank" Many text editors have features known as "cut and paste" or "copy and paste." vi calls the copy part of "copy and paste" a yank. You can use the yank command to save any block of text in the undo buffer. The undo buffer is a special place that vi keeps internally. You can't directly see the contents of this buffer. The contents of this buffer can be put into the text with the p command (see the following).

Each use of the y command overwrites the contents of the undo buffer, as does any delete command. There is a more advanced version of the yank command explained in the section "How To Use Buffers," which can be used to save text in multiple named buffers.

y--Yank The yank command works with an object in the same way as the c and d commands. You can yank a word with yw, yank to the end of the line with y$, yank three lines with 3yy.

Y--Big Yank There is an exception to the pattern however. For some reason, the Y command does not take its action to the end of the line as C and D do. Instead, it yanks the whole line, and is therefore identical to yy.

Copying Text The commands discussed in the following sections are used to copy text.

p--Put The p command takes whatever is in the undo buffer and inserts it into the text after the cursor position.

P--Big Put The P command takes whatever is in the undo buffer and inserts it into the text before the cursor position.

Moving Text In addition to text that you specifically yank being placed in the undo buffer, each portion of text that is deleted goes into the same undo buffer, replacing the previous contents each time. So to perform a cut and paste you would use any delete function, then move the cursor to the desired insertion point, then use one of the put commands to insert the text. You will have to pay attention to the location of the cursor and whether to use the p or P commands to get exactly what you want.

For example, suppose your screen appears as shown in the following example:

    If wise, a commander is able to recognize changing circumstances and to
act expediently.  If sincere, his men will have no doubt of the certainty of
rewards and punishments.  If humane, he loves mankind, sympathizes with others,
and appreciates their industry and toil.  If courageous, he gains victory by
seizing opportunity without hesitation.  If strict, his troops are disciplined
because they are in awe of him and are afraid of punishment.
    Shen Pao-hsu ... said: 'If a general is not courageous he will be unable
to conquer doubts or to create great plans.'
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~

Now suppose you wish you change the order of the paragraphs so that the paragraph beginning with "Shen Pao-hsu" comes first. First, move the cursor on to any character in the first line of the "Shen Pao-hsu" paragraph, as shown here:

    If wise, a commander is able to recognize changing circumstances and to
act expediently.  If sincere, his men will have no doubt of the certainty of
rewards and punishments.  If humane, he loves mankind, sympathizes with others,
and appreciates their industry and toil.  If courageous, he gains victory by
seizing opportunity without hesitation.  If strict, his troops are disciplined
because they are in awe of him and are afraid of punishment.
    Shen Pao-hsu ... said: 'If a general is not courageous he will be unable
to conquer doubts or to create great plans.'
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~

Then press 2dd to delete the second paragraph. Your screen will appear as in the following example:

    If wise, a commander is able to recognize changing circumstances and to
act expediently.  If sincere, his men will have no doubt of the certainty of
rewards and punishments.  If humane, he loves mankind, sympathizes with others,
and appreciates their industry and toil.  If courageous, he gains victory by
seizing opportunity without hesitation.  If strict, his troops are disciplined
because they are in awe of him and are afraid of punishment. ~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~

Now move the cursor to any character on the top line, as shown here:

    If wise, a commander is able to recognize changing circumstances and to
act expediently.  If sincere, his men will have no doubt of the certainty of
rewards and punishments.  If humane, he loves mankind, sympathizes with others,
and appreciates their industry and toil.  If courageous, he gains victory by
seizing opportunity without hesitation.  If strict, his troops are disciplined
because they are in awe of him and are afraid of punishment.
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~

Now use the p command to put the text. Oops! Your screen looks like this:

    If wise, a commander is able to recognize changing circumstances and to
    Shen Pao-hsu ... said: 'If a general is not courageous he will be unable to
act expediently.  If sincere, his men will have no doubt of the certainty of
rewards and punishments.  If humane, he loves mankind, sympathizes with others,
and appreciates their industry and toil.  If courageous, he gains victory by
seizing opportunity without hesitation.  If strict, his troops are disciplined
because they are in awe of him and are afraid of punishment. ~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~

This is not what we intended! To fix it, first press u to undo; then press P to put before the cursor. After a little practice, you will get used to easily accomplishing what you want to do.

You probably noticed during this exercise that you were able to use the put command repeatedly to put the same text. You are able to do this because the put command does not change the contents of the undo buffer. This feature sometimes comes in quite handy.

Searching for Patterns /, //, ?, ??, n, and N--Search One of the more useful ways of moving around in your text is to search for a pattern. You might be editing a long source code file, and want to go back to a routine that you remember contains a specific instruction. You can do this by using /, the forward search command, or ?, the backward search command. As soon as you type the slash or question mark while in command mode, the cursor moves to the command line. You then type the pattern that you wish to find. This pattern can be a literal text string, which is the exact character sequence you wish to find. Or it can be a regular expression, described in detail in the "Regular Expressions" section.

After pressing the Return key, the text is repositioned so that the line containing the first occurrence of the pattern is displayed approximately in the center of the screen (assuming there is enough surrounding text to permit this) and the cursor is positioned to the first character of the matched text. If the pattern is not found, the message "Pattern not found: pattern" is displayed on the command line.

You use the / command to search forward in the text (that is, from where the cursor is positioned to the end of the buffer). You use the ? command to search backward in the text (that is, from where the cursor is positioned to the top of the buffer). You can repeat either forward or backward searches without reentering the pattern by using the two search again commands (/ and ? without any search text--// and ?? also work). You must also enter the Return key after these search again commands. Once a pattern has been entered, you can intermix the forward and backward search commands.

Another variation on repeating search commands is to use the n command, which repeats the previous search in the same direction, whether forward or backward. The N command repeats the previous search in the opposite direction.

vi searches "wrap around" the top and bottom of the buffer. When searching for the pattern, if vi hits one end of the buffer, a message will display on the command line notifying you of this fact. For example, the message "search hit BOTTOM, continuing at TOP" may appear. At this point, you may press Return the continue the search. (This behavior can be changed; please refer to the "For the Power User: Customizing vi" section to see how you can use special settings to change vi's default behavior.)

How To Use Buffers

The undo buffer contains only the most recent yanked or deleted text. This means that if you were intending to yank some text and copy it in somewhere, but before you put the text you performed any other deletion, you would be disappointed with the result. In order to keep various text snippets available for putting you will have to use named buffers.

Named Buffers Named buffers allow you to keep up to 26 separate places where text can be deleted or yanked. Using the named buffers allows you to overcome the problem of intermediate deletes replacing the text that you have yanked or deleted. The contents of a named buffer remains unchanged until the end of your vi session, unless you use commands to deliberately change it.

Buffers are named by using a " followed by a lowercase letter. So the buffers are named from "a to "z. To yank or delete into a named buffer, prefix the yank or delete command with the name. For example, to yank two lines from the cursor position into buffer z, you would use the following keystrokes: "z2yy. To put from the named buffers, the key sequence is the buffer name followed by the p command. Table 3.5 following shows some examples of using named buffers (some object commands have not been introduced yet; I hope this will whet your appetite for more, rather than confuse you):

Table 3.5. Examples of using named buffers.

Keystrokes Result
"a2dw Delete next two words into named buffer a
"jD Delete from cursor to end of line into named buffer j
"jp Put the contents of named buffer j after the cursor
"by) Yank from cursor position to end of sentence into named buffer b

As with a normal yank into the regular (unnamed) undo buffer, the action of the yank or delete into the named buffer will replace the previous contents of that buffer. If, instead, you want to collect text in a named buffer by appending it to what is already there, you may do this by uppercasing the letter of the buffer's name. Yanks and deletes can be intermixed when using the appending method, as shown in the sequence in Table 3.6.

Table 3.6. Intermixed sequence of yanks and a delete.

Keystrokes Result
"a2yy Yank two lines into named buffer a, discarding the previous contents
"Ad4w Delete the next four words, and append them into buffer a
"Ay) Yank from the cursor to the end of the sentence, and append into buffer a


Caution: You will have to be careful in executing such a sequence not to forget to use the capital letter. If you forget, the previous contents are obliterated and your careful work is lost. For this reason, I seldom use this technique, and when I do use it, I do carefully!

Delete Buffers In addition to the named buffers, vi provides numbered delete buffers. A normal undo can only undo the last delete and only if it was the last edit. However, vi saves the most recent nine deletes in buffers numbered from 1 to 9. The most recent delete is kept in buffer 1, the next most recent in buffer 2, and so on. To recover the contents of one of these buffers, use the number as the buffer name with the p command, as in "2p to put from the second delete buffer.


Tip: How do you know what is in each of the delete buffers? A special feature of the . (repeat) command (described later in the "Recovering Deleted Text: Cutting and Pasting" section) allows you to easily choose from among the numbered buffers. When the repeat command is used after a command referencing a numbered buffer, the buffer number is incremented.
Thus you can put from numbered buffer 1, see the text that is inserted, use the u command to undo the put, then just press . (the repeat command) to see the next buffer's contents. Continuing this process with a series of u commands and . (repeat) commands will quickly scan through the nine most recent deletions. (When you get to the ninth one, continued key presses "stick" on the ninth buffers contents.) This is another technique that is a lot easier to do than to describe.

The Complete Guide to Movement and Editing: Command Reference Tables

By this point you have seen the most commonly used vi commands. However, there are many useful and powerful movement and editing commands that, while less frequently used, might become invaluable to you as you learn to use them. Some of them are likely to be included in your repertoire of often-used commands, sooner or later. This section is intended to provide complete coverage of the movement, editing, and other commands, for easy reference.

Note that some commands are shifted commands. Commands represented by uppercase letters are entered by holding down the Shift key while the alphabetic letter is pressed. So called control-key commands are entered in a similar fashion, with the Control key held down while the other key is pressed. Control-key commands are indicated in the vi sections by prefixing the command with a caret symbol (^), or alternately by the sequence Ctrl-key. So for example, when you see in the text the symbol ^A, this means you are to hold down the Ctrl key while you press the letter a. (Later, when discussing Emacs, I will adopt the standard Emacs way of indicating control keys--do not let this confuse you!)

Be aware that all of the commands shown in the table can be combined in the ways described in Table 3.3. That is, you can amplify the effect of commands by using a count or an object or both, as appropriate.

Some of the commands included here have not been introduced yet. They will be explained in detail in the advanced editing section.

Movement In Table 3.7 the following words in the command column have the specified meaning: char means any character; number (or nbr) is a whole number; pattern is a string of characters or a regular expression.

In the description column, a small word is a word that can be either a string of alphanumeric characters (plus the underscore) or a string of punctuation characters, delimited by white space (spaces, tabs, and line feeds); a big word is a sequence of non-blank characters. What these precise but technical definitions are saying, in effect, that small words consider the punctuation to be separate "words;" big words include the punctuation as part of the word. The easiest way to see the difference is first to try a repeated sequence of moves using the lowercase version of a command; then try the uppercase version of the command.

Table 3.7. Movement commands.

Single Character Cursor Motion
Command Result
h one character left
^H left-arrow
j one line down
^J down-arrow
^N one line up
k up-arrow
^P one character right
l right-arrow
Movement Within a Line
Command Result
^ first non-space character on the line
0 beginning of the line
$ end of line
fchar to next occurrence of character char
Fchar to previous occurrence of character char
tchar to character before next occurrence of character char
Tchar to character after previous occurrence of character char
; repeats previous f, F, t, or T command; same direction
, repeats previous f, F, t, or T command; opposite direction
Motion To a Specified Line
Command Result
Enter to next line
+ to next line (usually used with preceding count)
- to previous line (usually used with preceding count)
numberG to line number
number| to column number
Screen Positioning
Command Result
H to top line displayed on screen
L to bottom line displayed on screen
M to middle line displayed on screen
^D scroll down one-half screen
number^D scroll down number lines
^U scroll up one-half screen
number^U scroll up number lines
^F scroll forward one screen
^B scroll backward one screen
^E scroll down one line
^Y scroll up one line
Lexical Object Positioning
Command Result
w forward one small word
W forward one big word
b backward one small word
B backward on big word
e to end of next small word
E to end of next big word
( to beginning of previous sentence
) to beginning of next sentence
{ to beginning of previous paragraph
{ to beginning of next paragraph
[[ to beginning of next section
]] to beginning of previous section
Screen Redrawing
Command Result
z redraws screen with current line at top of the screen
z- redraws screen with current line at bottom of the screen
z. redraws screen with current line at center of the screen
Positioning by Pattern Searching
Command Result
/pattern moves to next line containing pattern
?pattern moves to previous line containing pattern
/ repeats last search forward
? repeats last search backward
n repeats last search in same direction
N repeats last search in opposite direction
/pattern/+nbr to nbr lines after next line containing pattern
?pattern?-nbr to nbr lines before previous line containing pattern
/pattern/z- redraws screen with next line containing pattern at bottom of the screen (other z options will give the corresponding positioning)
% to parenthesis or brace matching the one at the current cursor position
Positioning to Marked Text Locations
Command Result
mchar marks the current cursor position with the letter char
'char to mark specified by char
'char to beginning of line containing mark specified by char
'' to previous location of the current line (after a cursor movement)
'' to beginning of line containing previous location of current line (after a cursor movement)

Editing In Table 3.8 the words in the command column have the specified meaning: object means an object command from Table 3.7; letter means one of the 26 alphabetic characters from a to z. All editing commands can take nearly any movement command as an object. The text insertion commands cause entry into insert mode; vi then stays in that mode until you press the Esc key.

Table 3.8. Editing commands.

Inserting Text
Command Result
i inserts text before the cursor
I inserts text before first non-blank character of line
a inserts text after the cursor
A inserts text at the end of the line
o adds an empty line below the current line and enters insert mode there
O adds an empty line above the current line and enters insert mode there

(Note: These commands are only available while in insert mode.)
Changing Text While in Insert Mode
Command Result
^H backspaces and erases the previous character (only since insert began)
^W backspaces over and erases the previous small word (only since insert began)
\ quotes the erase and kill characters
Esc ends insert mode and go back to command mode
^D back to previous auto-indent stop
^^D (caret followed by Ctrl-D) no auto-indent on current line only
0^D moves cursor back to left margin
^V enters any character into text (do not interpret control characters)
Changing Text
Command Result
cobject changes the text object to the text inserted until the Esc key is pressed
C changes the rest of the line to the text insert until the Esc key is pressed (same as c$)
cc changes the whole line to the text inserted until the Esc key is pressed
rchar replaces the character the cursor is on with char; then return to command mode
R overwrites text until the Esc key is pressed; if you go past the end of the line, append new text to the end of the line
s substitutes characters (same as cl)
S substitutes lines (same as cc)
Deleting Text
Command Result
x deletes the character under the cursor
X deletes the character before the cursor
dobject deletes the text object
D deletes the reset of the line (same as d$)
dd deletes the line
Using Buffers
Command Result
u undo the last change
U restores the current line to the state it was in when the cursor was last positioned to it
yobject places the text of the object into the undo buffer
yy places the line the cursor is on into the undo buffer
Y places the line the cursor is on into the undo buffer (same as yy, which is a departure from the pattern set up by C and D)
p inserts the text in the undo buffer after the cursor
P inserts the text in the undo buffer before the cursor
"letterdobject deletes the object into the letter buffer
"letteryobject yanks (copies) the object into the letter buffer
"letterp inserts the text in the letter buffer after the cursor
"numberp inserts the number-th last delete of a complete line or block of lines
Other Editing Commands
Command Result
. repeats the last editing command (and increments n in a "np command)
~ changes the case of the letter under the cursor and moves cursor to left one character (does not support a count in standard vi)
J joins two lines
>> shifts line shiftwidth characters to the right (use :set sw to change the shiftwidth)
>L shifts all lines from the line the cursor is on to the end of the screen shiftwidth characters to the right (use :set sw to change the shiftwidth)
<< shifts line shiftwidth characters to the left (use :set sw to change the shiftwidth)
<L shifts all lines from the line the cursor is on to the end of the screen shiftwidth characters to the left (use :set sw to change the shiftwidth)

Other vi Commands In Table 3.9, commands that start with : (colon) are ex commands. If these are being executed from within the ex editor, you do not need the colon. When the ! modifier is included with a command, some form of override will be performed. Not all combinations that include the ! are shown.

In the command column, the following words have the specified meaning: file means the name of a disk file; number or nbr means a positive whole number; command or cmd means a UNIX shell command; tag means a function identifier created using the ctags program; addr means an ex line address (defined in the "Using the Power of ex from vi" section following).

Table 3.9. Other vi commands.

Saving the Buffer to a File
Command Result
:w writes (saves) the buffer to disk, using the original file name
:w file writes the buffer to disk, to file
:w! writes the buffer to disk, overwriting file
Exiting Commands
Command Result
ZZ writes the buffer to disk and exits the program
Q enters the ex editor (same as typing :)
:q quit vi, unless you have an unsaved buffer
:q! always quits vi, overriding warning about an unsaved buffer
:wq writes the buffer to disk and exits the program (same as ZZ)
Editing Other Files
Command Result
:e file edits file, unless you have an unsaved buffer
:e! discards any changes and starts over with the last saved version of the file from disk
:e + file edits file, unless you have an unsaved buffer; places cursor bottom line
:e +nbr file edits file, unless you have an unsaved buffer; places cursor on line nbr
:e # edits alternate file
:n edits the next file (applies when a list of files was entered on the command line)
:n file file file sets up a new list of files to edit
:r file reads (inserts) contents of file into the buffer on the line below the cursor
:r !command runs the shell command and inserts the output of the command on the line below the cursor
^G displays information about the current file (filename, current line number, number of lines in file, percentage through the file)
:ta tag jumps to the file and the location in the file specified by tag (before you can use this function, you must use the ctags program to create the tags file. Refer to the section on the :ta command for details.)
Redrawing the Screen
Command Result
^L redraws the screen (implementation depends upon terminal type)
^R redraws the screen; eliminates blank lines marked with @ (implementation depends upon terminal type)
znumber sets screen window to number lines
UNIX Shell Commands
Command Result
:sh executes a shell; remain in shell until shell exit command given (^D)
:!command executes the shell command and returns to vi (after the ! command, certain special characters are expanded. # is expanded to the alternate file name; % is expanded to the current file name; ! is expanded to the previous shell command)
:!! repeat the previous shell command
!object cmd execute the shell cmd; replace the text object with the shell cmd output. If the shell cmd takes standard input, the designated text object is used.
nbr!!cmd execute the shell cmd; replace nbr lines beginning at the current line with the shell cmd output. If nbr is missing, 1 is assumed. If the shell cmd takes standard input, the designated lines are used.
ex Editing Commands
Command Result
:vi enters visual mode from the ex command line
:addrd delete the lines specified by addr
:addrmnbr move the lines specified by addr after line nbr
:addrconbr copy the lines specified by addr after line nbr
:addrtnbr copy the lines specified by addr after line nbr (same as co command)

Advanced Editing: Tips and Techniques

You may be ready for the any of the topics included in this section at any time while you are learning vi. Do not let the title of the section deter you from browsing for features that interest you. While some vi commands are less often used, the real power of the vi editor will not be fully yours until you are comfortable with at least some of these features.

Using the Power of ex from vi

As mentioned in the section "Full-Screen Editors versus Line Editors," vi is actually the visual mode of the ex editor. As such, all of the power and features of the ex editor are available at any time while editing in vi, without leaving your place in the file. vi commands that are actually ex commands are shown in the command reference tables and elsewhere in this chapter prefixed with a : (colon). You can think of this prefix in either of two ways: (1) as a prefix to a special vi command; or, (2) the command that takes the editor into ex mode, at which time the screen display changes so that a colon is displayed on the bottom line and the cursor is placed immediately to the right of the colon. Thereafter, the editor will act exactly the same as if you were in the ex editor, except that you will still have the vi screen displayed on all lines but the bottom line. Certain commands will return you to the vi mode; others will leave you in the ex mode. To return explicitly to the vi mode, just enter the :vi command.

The real power of using ex commands from within vi is that certain specific editing functions are provided in this way that are usually not available in most text editors. (The power of such operations is approached by macro languages included with PC-based word processing programs; however, the simplicity and elegance of the ex commands are not.)

The types of operations that are available only from the ex command line are using basic ex commands to manipulate blocks of text, search and replace operations, global search and replace with regular expressions, and edit multiple files.

Using Basic ex Commands to Manipulate Blocks of Text

ex has its own versions of delete, copy, and move commands. Sometimes these commands are preferable to the vi versions, particularly when you want to manipulate the file as a whole. The main ex commands for these operations will be covered here.

First, let's look at the general form of an ex command. An ex command is composed of an object and an operation to perform on the lines in the file that are selected by the object. The general form is

:object command Return

where Return means to press the Return key. All ex commands require the Return key (which is labeled Enter on a PC keyboard) to be pressed. The spaces shown in the preceding example can be used if desired for readability, but they are not necessary.

Rather than using the vi concepts of a full-screen display with the cursor position to indicate where actions will take place, ex has the concept of a current line. This concept means that ex will take its action on or relative to that line.

Both the object and command are optional. If the object is missing, the default is to apply the command to the current line. If the command is missing, the default is the ex print command, which displays the selected lines on the screen. Spaces between the parts of the command are also optional. In the examples, spaces are included to for clarity.

When using the ex editor from the command line (that is, you are not running from within vi), ex responds to each command by displaying the lines effected. In the examples that follow, the behavior of the ex editor is shown with the assumption that you are using it from the command line, rather than from within vi. You may wish to get a feel for the pure ex mode of interaction by trying it from the command line. When operating from within vi, the effect on the text you are editing is shown, just as if you executed the equivalent vi command. The screen display is repositioned if necessary.

The ex editor can be entered from within vi to edit the file you are currently editing by typing :. It can also be started from the command line with the name of the file you wish to edit. If you start if from the command line in this way, you may see the following on your screen (assuming you are editing the same sample file that we have been using all along):

$ex art1
"art" 8 lines, 576 characters
:

Selecting Lines to Edit

Sets of lines may be selected in several ways. Because you already know that ex is a line editor, it is not surprising that line addresses refer to lines in the file without regard to content. The simplest way to address a line is with its number. For example, to print line three of your file, you could enter the following command:

:3p
rewards and punishments. If humane, he loves mankind, sympathizes with others,

Another way to give an address is with a pattern search. A pattern search is indicated by surrounding the exact character string you are looking for with forward slashes. For example, to display on the screen the first line of your file containing the word "general" you could enter the following command:

:/general/p
Shen Pao-hsu ... said: 'If a general is not courageous he will be unable

In both of these last two examples, you could leave off the p command, because as mentioned already, the p command is the default.

You may also specify a range of lines by entering two addresses separated by commas, as in the following example:

:3,6p
rewards and punishments. If humane, he loves mankind, sympathizes with others,
and appreciates their industry and toil.  If courageous, he gains victory by 
seizing opportunity without hesitation.  If strict, his troops are disciplined

Patterns also work in range selection, as in the following example:

:/humane/,/hesitation/p
rewards and punishments. If humane, he loves mankind, sympathizes with others, 
and appreciates their industry and toil.  If courageous, he gains victory by 
seizing opportunity without hesitation.  If strict, his troops are disciplined

You can mix patterns and line numbers too:

:4,/awe/p
and appreciates their industry and toil.  If courageous, he gains victory by 
seizing opportunity without hesitation. If strict, his troops are disciplined 
because they are in awe of him and are afraid of punishment.

There are special ex line addressing symbols that can be used as addresses. Line addressing takes on greater flexibility when you add these capabilities to the ones you already know. The special symbols are shown in Table 3.10:

Table 3.10. Special ex line addressing symbols.

Command Result
. the current line
$ the last line of the file
% every line in the file

Another feature to allow greater flexibility in line addressing is line number arithmetic. This feature allows you to use the + and - symbols along with numbers to refer to offsets from the position specified. For example, to refer to 20 lines from the current line number, you would use .+20.

When using two line addresses, the second address cannot be less than the first address. Sometimes when you try to use search patterns to select a line or line number arithmetic, you may get the error message ex: The first address cannot exceed the second address. This is because both line addresses are determined relative to the current line. In this case, you will get an error message. What you really wanted was to have the second address be determined relative to the first address. ex has a feature that causes the second line address to be relative to the first. You use this feature by using a semi-colon between the two addresses instead of a comma.

Table 3.11 following shows several examples of all of the various methods of line addressing presented so far.

Table 3.11. Various methods of line addressing.

Command Result
1,5 lines 1 through 5
.,20 from the current line to line 20
.,.+20 20 lines beginning at the current line
.,$ from the current line to the end of the file
1,$ all lines in the file (same as %)
8,/pattern/ from line 8 to the next line containing pattern
5;.+20 from line 5 to 20 lines beyond line 5

Basic ex Commands

ex has the property that every command has a name. You can enter the full name of the command, or any length abbreviation of the command that sufficiently distinguishes it from all other commands. As I introduce new ex commands, I will first use the full command name. However, the examples will use the shortest possible abbreviation of the command, because that is the way you will wish to use them. Table 3.12 following shows a few of the basic ex commands:

Table 3.12. Basic ex commands.

Command Result
d delete
m move
co copy
t copy (synonym for co)

Table 3.13 following presents examples of various ex editing commands. It summarizes the information given in this section on manipulating blocks of text.

Table 3.13. Examples of ex editing commands.

Command Result
1,5d delete lines 1 through 5
.,20m$ move the current line through line 20 to the end of the file
.,.+20co0 copy 20 lines beginning at the current line to the top of the file
8,/pattern/t. copy from line 8 to the next line containing pattern to the point after the current line

In this section, I have introduced some of the basic ex commands that are useful to extend the power of vi. There are several additional ex commands that provide an alternate way of doing various editing tasks. However, all of these are more easily done by using the features of vi. Therefore, such commands are not covered here.

Search and Replace

One of the main uses for ex commands from within vi (in addition to working with files and exiting the program) is to execute search and replace operations. In this section, basic search and replace operations are introduced. The next section introduces the topic of regular expressions. Regular expressions are extraordinarily powerful tools to search for text. If you are familiar with so-called "wildcard" searches offered by certain text manipulation tools, you can think of regular expressions as "wildcards on steroids!" The use of regular expressions for searching is covered in the second section following this one.

Simple search and replace operations are done in ex (and, therefore, in vi) by using the substitute command. Unless line addressing is used (see the following), the substitute command operates on the current line, so it is necessary to move the cursor to the line you want edit first. The following example assumes that you want to substitute the word "opportunities" for the word "plan" in line 8 of the sample text. Note that the final slash is required:

:8                         Position to line 8 of the buffer
:s/plans/opportunities/    Replace "plans" with "opportunities" on the current line

You can also perform search and replace operations on the entire file, or a selected range of lines. Table 3.14 following shows examples of using the substitute command to operate on all lines in the buffer, or a selected range of lines.

Table 3.14. Using the substitute command.

Command Result
:%s/warrior/general/g Replace every occurrence in the buffer of warrior with general.
:.,.+20s/warrior/general/ Replace the first occurrence of warrior with general on 20 lines beginning with the current line.

Another way to search is to use the global command, as shown here:

:g/plans/command

When used in this way, the command is performed on all lines that match the pattern. To negate the action of the search (that is, to act on all lines which do not match the pattern), use :g!.

If the global command is used without the final slash and the command, the cursor will be positioned to the last line in the file that contains the pattern (or does not contain the pattern, if ! is used). If no match is found, the screen will not be changed and the cursor will stay where it is. (There is little point to using the global command to search in this way--use the vi / or ? instead.)

You can use the global command with line addressing to limit the scope of its action. Examples of using the global command with other commands are shown in Table 3.15.

Table 3.15. Using the global command with other commands.

Command Result
:g/22/d Delete all lines containing 22.
:g/plans/p Display all lines containing plans.
:g!/22/d Delete all lines not containing 22.
:8,12g/plans/p Display all lines between lines 8 and 12 containing plans.

The global command can also be used to perform replacements. However, the real power of this command for replacements does not emerge until you begin to use it with regular expressions, which are explained in the next section.

Regular Expressions

Regular expressions are patterns used in search and replace operations that vastly extends the power and flexibility of the editing you can do. Regular expressions include in addition to literal characters, combinations of so-called metacharacters, which have special properties. Table 3.16 shows all of the metacharacters available for use within vi. (While there are a number of UNIX tools that can operate on regular expressions such as grep, sed, awk, certain metacharacters shown in the table are not implemented for these other tools. Such vi-and-Emacs-only metacharacters are indicated by the comment "editors only.")

Table 3.16. Metacharacters available with vi.

Metacharacter Matches
. Any single character, except a newline
* Zero or more occurrences of the previous character
^ When the first character of the regular expression, the beginning of a line
$ When the last character of the regular expression, the end of a line
\< The first character of a word (editors only)
\> The last character of a word (editors only)
\ The escape character; alters ("escapes from") the standard interpretation of the following character. For example, to search for the literal presence of a metacharacter, you must escape the character by preceding it with a backslash.
[ ] Any single character within the brackets; ranges may be used with a hyphen. For example, [a-z] matches all lowercase letters, [a-zA-Z] matches both lower- and uppercase characters. When metacharacters (other than ^) appear within square brackets, they do not need to be escaped. The literal hyphen can be included by placing it as the first character after the left square bracket
[^ ] Any single character not within the brackets
\( \) In a search pattern, saves the text matched within the escaped parenthesis in a numbered buffer for later "replaying" (the number is the position in the line as it is scanned from left to right; the first occurrence of this metacharacter pair is numbered 1, the second occurrence 2, and so on)
\n In a replacement pattern, where n is a digit from 1 to 9, "replays" the text saved by the escaped parenthesis
& Uses the entire search pattern which produced the match; used to save typing
\u or \l In a replacement pattern, causes the next character to be either upper- or lowercased
\U or \L In a replacement pattern, causes the rest of the replacement pattern (or until a \e or \E is scanned) to be upper- or lowercased
\e or \E In a replacement pattern, terminates the action of \U or \L
~ Matches the search pattern of the last regular expression search


CAUTION: The use of metacharacters might vary in different contexts. The shells use metacharacters for file name expansion; however, the interpretation of the metacharacters by the shells is slightly different from the interpretation by the utilities and text editors. (A shell is the name given to the UNIX command processor. There are several common versions of shell programs. The most common are sh, csh, ksh, and bash. Please refer to Part 2, "UNIX Shells" in UNIX Unleashed, System Administrator's Edition, for an extensive discussion on this topic.) This may be a source of confusion, especially to the newcomer. To make matters worse, the implementation of metacharacters differs between different UNIX versions.


TIP: All regular expression matches are limited to a single line. That is, a match that "wraps around" from the end of one line to the beginning of the next is not allowed.


TIP: All regular expression searches are case sensitive. You have to explicitly use the features of the metacharacters to perform case-insensitive searches. For example, if you wish to perform a search for the word "general" that is case-insensitive on the initial "g," you should use /[Gg]eneral/ for the search string.


TIP: Regular expressions are usually delimited by forward slash (/) characters. However, any non-alphanumeric character other than ", |, or # can be used. This is especially helpful when the slash is one of the characters in the search string and you don't want to escape the slash.

Global Search and Replace with Regular Expressions

You have already seen how to perform searches from vi using the / and ? commands. As mentioned when these commands were introduced, you can use these commands with regular expressions as well as with literal text strings. There are two ways to use regular expressions to perform search and replace operations. Both methods work from the ex command line, and both are extensions of commands you have been exposed to in the "Search and Replace" section. One way is to use the substitute command; the other way is through the use of the global command.

Using the Substitute Command with Regular Expressions

When you wish to make a global replacement, you can use the substitute command with line addressing and regular expressions. A commonly used form is to use the % addressing symbol to refer to all lines in the file. The general form of such a command is as follows:

:address s/searchexpression/replaceexpression/options

(The space after address in the preceding example is for clarity and is optional.) The options refer to one of the options shown in Table 3.17.

Table 3.17. Substitute options.

Command Result
g Make the substitution global (Without this option, the substitution only occurs on the first occurrence in the line; with it all occurrences on the line are substituted. Do not confuse this option to the substitute command, which is placed at the far right of the command, with the global command itself, which occurs on the left of the command line near the colon.)
c

Confirm. vi displays each line found and indicates the text to be substituted with '^' symbols as follows:

this is some text ^^^^

You must enter a "y" to make the substitution; any other response causes the substitution not to be made. (Note: Some versions of vi handle this a little differently, using text highlighting to indicate the pattern matched, and allowing additional choices at each step.)

You may combine both of these options into one substitute command.

Using the Global Command with Regular Expressions

The global command becomes very powerful when combined with the substitute command. One interesting way to use this combination is to use the global command to select the lines, and then use the substitute command to cause a change on the lines that does not directly relate to the text the caused the line to be selected.

In effect, what the global command does is to provide a two-step editing function. First, a set of lines is selected using several of various techniques (line addressing and pattern matching). Then another command is used upon the lines selected. When the global command was first introduced in this chapter, it was used in a simple way with other commands to display or delete text. In fact, the global command can be used with most any other command. (There are some creative techniques, indeed, that have been invented that use the global command. Some are shown in the examples of Table 3.18.)

The best way to show how the substitute command works and how the global and substitute commands can be used together is to present some examples. Table 3.18 shows a few of the types of search and replace operations that can be done. (Note: For clarity, the bolded lowercase letter b is used to indicate a single blank space.)

Table 3.18. Examples of search and replace with the s and g commands.

Command Result
:%s/ex/vi/g Substitute every occurrence of ex in the buffer with vi.
:.,$s/ex/vi/c Substitute the first occurrence of ex with vi on every line from the current line to the end of the buffer, confirming each substitution.
:%s/\<author\>/contractor/g Substitute the word contractor for each occurrence of the full word author in the buffer; note that text objects containing author as a substring, such as authority will not be substituted.
:g/editor/s/line/full-screen/g Substitute every occurrence of line with full-screen on all lines containing the pattern editor
:g/editor/s//word-processor/g Substitute every occurrence of editor with word-processor; note that when the second search string is missing, the first search string is used; in this case, the string editor
:%s/bb*/b/g Substitute a single space for every occurrence of one or more spaces (note: the b stands for a single space).
:%s/[:.]bb*\([a-z]\)/\.bb\u\1/g Search for all occurrences of a colon or a period followed by one or more spaces and a lowercase letter; substitutes a period, two spaces and the uppercase form of the letter.
:g/^$/d Delete all blank lines (lines that have only a beginning followed immediately by the end)
:g/^/m0 Reverse all the lines in the buffer
:g!/Complete/s/$/ To be done/ Append To be done to all lines not containing the string Complete

Working with Files

The basic commands for saving files were introduced in the "Starting Up and Exiting vi" section. This section will more fully explain these commands and show how to use them to work with more than one file at a time.

Saving Changes to a File

:w--Write The w command is used to write the buffer to the current disk file. The current disk file is the one that was most recently loaded for editing, either from the command line when vi was started, or using the :e command. If there is no current disk file (perhaps because vi was loaded without specifying a file to edit), vi will display an error message and no action will occur. In this case, you can give a name to the current disk file with the version of the :w presented next.

Until the buffer is written to disk, all edits to the file are only stored temporarily. It is, therefore, a good habit to develop to save your work frequently during your session to minimize the inconvenience of a system failure or major editing error that may occur.

:w filename--Write to filename This version of the write command will save the buffer to the named filename. If there was previously no current file defined, the filename will become the current file. Otherwise, the current file will remain the same as it was before the :w filename command was issued.

If the filename file already exists, as usual vi warns you of this fact with an error message, and gives advice on how to override the warning, as follows for a file name art1:

     "art1" ex: The file already exists. Use w! art1 to force the write.

If you do in fact wish to overwrite the existing version, you can use the syntax :w! filename.

:address w filename--Write addressed lines to filename This version of the write command further refines the action of the :w