If you like primitive tools, you've already figured out that you can use a combination of << and cat to add lines to a file, and you can use sed and file redirection to modify the contents of a file. These tools are rough and awkward, and when
it's time to either create new files or modify existing ones, you need a screen-oriented editor. In UNIX, the screen editor of choice is called vi.
There are a number of editors that may be included with your UNIX system, including ed, ex, vi, and EMACS. The latter two use the entire screen, a big advantage, and both are powerful editors. This section focuses on vi, however, because it's easier
and, perhaps more importantly, it's guaranteed to always be part of UNIX. Most vendors omit EMACS, forcing you to find it yourself.
In this section, you will learn how to start and quit vi, simple character motion in vi, how to move by words and pages, how to insert text into the file, how to search within a file, how to have vi start out right, the key colon commands in vi.
In some ways, an editor is like another operating system living within UNIX. If you're used to Windows or Macintosh editors, you'll be unhappy to find that vi doesn't know anything about your mouse. Once you spend some time working with vi, however, it
will grow on you. By the end of this section, you will be able to create and modify files on your UNIX system to your heart's content.
Most UNIX commands do their work, display their results, and quit. Among the few exceptions are more and pg, where you work within the specific program environment until you have viewed the entire contents of the file being shown, or until you quit. The
vi editor is another program in this small category of environments, programs that you move in and use until you explicitly tell the program to quit.
Before you start vi for the first time, you must learn about two aspects of its behavior. The first is that vi is a modal editor. A mode is like an environment. Different modes in vi interpret the same key differently. For example, if you're in insert
mode, pressing the A key adds an a to the text, whereas in command mode, pressing the A key enters a, a single key abbreviation for the append command. If you ever get confused about what mode you're in, press the Esc key on your keyboard. Pressing Esc
always returns you to the command mode (and if you're already in command mode, it beeps to remind you of that fact).
The second important characteristic of vi is that it's a screen-oriented program. It must know what kind of terminal, computer, or system you're using to work with UNIX. This probably won't be a problem for you, because most systems are set up so that
the default terminal type matches the terminal or communications program you're using. Here you will learn how to recognize when vi cannot figure out what terminal you're using, and what to do about it.
You can start vi in a number of different ways, and you will learn about lots of helpful alternatives later. Right now you will learn the basics. The vi command by itself starts the editor, ready for you to create a new file. The vi command with a
filename starts vi with the specified file, so you can modify that file immediately.
To begin, enter vi at the prompt. If all is working well, the screen will clear, the first character on each line will become a tilde (~), and the cursor will be sitting at the top-left corner of the screen:
% vi _ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
Type a colon character. Doing so moves the cursor to the bottom of the screen and replaces the last tilde with a colon:
~ ~ ~ ~ ~ ~ ~ ~ :_
Press the q key and the Enter key, and you should be back at the shell prompt:
~ ~ ~ ~ ~ ~ ~ ~ :q %
If that operation worked without a problem, go ahead and append your command to your .login or .profile file. If the operation did not work, you received the unknown-terminal-type error message. You might see this on your screen:
% vi "unknown": Unknown terminal type I don't know what type of terminal you are on. All I have is "unknown" [using open mode] _
Alternatively, you might see this:
% vi Visual needs addressible cursor or upline capability :
Don't panic. You can fix this problem. The first step is to get back to the shell prompt. To do this, do exactly what you did in the first step: type :q and press Enter. You should then see this:
% vi "unknown": Unknown terminal type I don't know what type of terminal you are on. All I have is "unknown" [using open mode] :q %
The problem here is that vi needs to know the type of terminal you're using, but it can't figure that out on its own. Therefore, you need to tell this to the operating system by setting the TERM environment variable. If you know what kind of terminal
you have, use that value; otherwise, try the default of vt100:
% setenv TERM vt100
If you have the $ prompt, which means you're using the Bourne shell (sh) or Korn shell (ksh) rather than the C shell (csh), try this:
$ TERM=vt100 ; export TERM
Either way, you can now try entering vi again, and it should work. If it does work, append the command (whichever of these two commands was successful for you) to your .login file if you use csh, or to .profile if you use sh or ksh:
% echo "setenv TERM vt100" >> .login
or
$ echo "TERM=vt100 ; export TERM" >> .profile
This way, the next time you log in, the system will remember what kind of terminal you're using.
If this didn't work, it's time to talk with your system administrator about the problem or to call your UNIX vendor to find out what the specific value should be. If you are connected through a modem or other line, and you are actually using a terminal
emulator or communications package, then you might also try using ansi as a TERM setting. If that fails, call the company that makes your software and ask them what terminal type the communications program is emulating.
Great! You have successfully launched vi, seen what it looks like, and even entered the most important command: the quit command. Now create a simple file and start vi so it shows you the contents of the file:
% ls -l > demo % vi demo total 29 drwx 2 taylor 512 Nov 21 10:39 Archives/ drwx 3 taylor 512 Dec 3 02:03 InfoWorld/ drwx 2 taylor 1024 Dec 3 01:43 Mail/ drwx 2 taylor 512 Oct 6 09:36 News/ drwx 4 taylor 512 Dec 2 22:08 OWL/ -rw-rw 1 taylor 126 Dec 3 16:34 awkscript -rw-rw 1 taylor 165 Dec 3 16:42 bigfiles drwx 2 taylor 512 Oct 13 10:45 bin/ -rw-rw 1 taylor 0 Dec 3 22:26 demo -rw-rw 1 taylor 12556 Nov 16 09:49 keylime.pie -rw-rw 1 taylor 8729 Dec 2 21:19 owl.c -rw-rw 1 taylor 199 Dec 3 16:11 sample -rw-rw 1 taylor 207 Dec 3 16:11 sample2 drwx 2 taylor 512 Oct 13 10:45 src/ drwxrwx 2 taylor 512 Nov 8 22:20 temp/ -rw-rw 1 taylor 582 Nov 27 18:29 tetme ~ ~ ~ ~ ~ ~ ~ "demo" 17 lines, 846 characters
You can see that vi reads the file specified on the command line. In this example, my file is 17 lines long, but my screen can hold 25 lines. To show that some lines lack any text, vi uses the tilde on a line by itself. Finally, note that, at the
bottom, the program shows the name of the file, the number of lines it found in the file, and the total number of characters.
Type :q again to quit vi and return to the command line for now. When you type the colon, the cursor will flash down to the bottom line and wait for the q, as it did before.
You have learned the most basic command in vithe :q commandand survived the experience. It's all downhill from here.
Getting to a file isn't much good if you can't actually move around in it. Now you will learn how to use the cursor control keys in vi. To move left one character, press the h key. To move up, press the k key. To move down, press the j key. To move
right a single character, use the l key. You can move left one character by pressing the Backspace key, and you can move to the beginning of the next line with the Enter key.
Launch vi again, specifying the demo file:
% vi demo total 29 drwx 2 taylor 512 Nov 21 10:39 Archives/ drwx 3 taylor 512 Dec 3 02:03 InfoWorld/ drwx 2 taylor 1024 Dec 3 01:43 Mail/ drwx 2 taylor 512 Oct 6 09:36 News/ drwx 4 taylor 512 Dec 2 22:08 OWL/ -rw-rw 1 taylor 126 Dec 3 16:34 awkscript -rw-rw 1 taylor 165 Dec 3 16:42 bigfiles drwx 2 taylor 512 Oct 13 10:45 bin/ -rw-rw 1 taylor 0 Dec 3 22:26 demo -rw-rw 1 taylor 12556 Nov 16 09:49 keylime.pie -rw-rw 1 taylor 8729 Dec 2 21:19 owl.c -rw-rw 1 taylor 199 Dec 3 16:11 sample -rw-rw 1 taylor 207 Dec 3 16:11 sample2 drwx 2 taylor 512 Oct 13 10:45 src/ drwxrwx 2 taylor 512 Nov 8 22:20 temp/ -rw-rw 1 taylor 582 Nov 27 18:29 tetme ~ ~ ~ ~ ~ ~ ~ "demo" 17 lines, 846 characters
You should see the cursor sitting on top the t in total on the first line, or perhaps flashing underneath the t character. Perhaps you have a flashing box cursor or one that shows up in a different color. In any case, that's your starting spot in the
file.
Press the h key once to try to move left. The cursor stays in the same spot and vi beeps to remind you that you can't move left any farther on the line. Try the k key to try to move up; the same thing will happen.
Now try pressing the j key to move down a character:
total 29 drwx 2 taylor 512 Nov 21 10:39 Archives/ drwx 3 taylor 512 Dec 3 02:03 InfoWorld/ drwx 2 taylor 1024 Dec 3 01:43 Mail/
Now the cursor is on the d directory indicator on the second line of the file.
Press the k key to move back up to the original starting spot.
Using the four cursor control keys (h, j, k, and l), move around in the file for a little bit until you are comfortable with what's happening on the screen. Now try using the Backspace and Enter keys to see how they help you move around.
Move to the middle of a line:
total 29 drwx 2 taylor 512 Nov 21 10:39 Archives/ drwx 3 taylor 512 Dec 3 02:03 InfoWorld/ drwx 2 taylor 1024 Dec 3 01:43 Mail/
Here you're middle digit in the file size of the second file in the listing. Here are two new cursor motion keys: the 0 (zero) key moves the cursor to the beginning of the line, and $ moves it to the end of the line. First, press 0:
total 29 drwx 2 taylor 512 Nov 21 10:39 Archives/ drwx 3 taylor 512 Dec 3 02:03 InfoWorld/ drwx 2 taylor 1024 Dec 3 01:43 Mail/
Now press $ to move to the end of the line:
total 29 drwx 2 taylor 512 Nov 21 10:39 Archives/ drwx 3 taylor 512 Dec 3 02:03 InfoWorld/ drwx 2 taylor 1024 Dec 3 01:43 Mail/
If you have arrow keys on your keyboard, try using them to see if they work the same way the h, j, k, and l keys work. If the arrow keys don't move you around, they might have shifted you into insert mode. If you type characters and they're added to the
file, you need to press the Esc key to return to command mode. Wrap this up by leaving this edit session. Because vi now knows that you have modified the file, it will try to ensure that you don't quit without saving the changes:
~ ~ :q No write since last change (:quit! overrides)
Use :q! (shorthand for :quit) to quit without saving the changes.
Stay in this file for the next section if you'd like, or use :q to quit.
Moving about a file using these six simple key commands is, on a small scale, much like the entire process of using the vi editor when working with files. Stick with these simple commands until you're comfortable moving around, and you will be well on
your way to becoming proficient with vi.
The description of the EMACS editor mentioned that because it's always in insert mode, all commands must include the Ctrl key. Well, it turns out that vi has its share of Ctrl+key commands, commands that require you to hold down the Ctrl key and press
another key. In this section, you will learn about Ctrl+F, Ctrl+B, Ctrl+U, and Ctrl+D. These move you forward or backward a screen, and up or down half a screen of text, respectively.
Here are a few more commands: Ctrl+w moves you forward word by word, Ctrl+b moves you backward word by word, and the uppercase versions of these two commands have very similar, but not identical, functions.
To see how this works, you need to create a file that is larger than your screen. An easy way to do this is to save the output of a common command to a file over and over until the file is long enough. The system I use has lots of users, so I needed to
use the who command just once. You might have to append the output of who to the big.output file a couple of times before the file is longer than 24 lines. (You can check by using wc, of course.)
% who > big.output; wc -l big.output
40
% vi big.output
leungtc ttyrV Dec 1 18:27 (magenta)
tuyinhwa ttyrX Dec 3 22:38 (expert)
hollenst ttyrZ Dec 3 22:14 (dov)
brandt ttyrb Nov 28 23:03 (age)
holmes ttyrj Dec 3 21:59 (age)
yuxi ttyrn Dec 1 14:19 (pc115)
frodo ttyro Dec 3 22:01 (mentor)
labeck ttyrt Dec 3 22:02 (dov)
chenlx2 ttyru Dec 3 21:53 (mentor)
leungtc ttys0 Nov 28 15:11 (gold)
chinese ttys2 Dec 3 22:53 (excalibur)
cdemmert ttys5 Dec 3 23:00 (mentor)
yuenca ttys6 Dec 3 23:00 (mentor)
janitor ttys7 Dec 3 18:18 (age)
mathisbp ttys8 Dec 3 23:17 (dov)
janitor ttys9 Dec 3 18:18 (age)
cs541 ttysC Dec 2 15:16 (solaria)
yansong ttysL Dec 1 14:44 (math)
mdps ttysO Nov 30 19:39 (localhost)
md ttysU Dec 2 08:45 (muller)
jac ttysa Dec 3 18:18 (localhost)
eichsted ttysb Dec 3 23:21 (pc1)
sweett ttysc Dec 3 22:40 (dov)
"big.output" 40 lines, 1659 characters
Because I have only a 25-line display and the output is 40 lines long (you can see that on the status line at the bottom), there is more information in this file than the screen can display at once.
To see the next screenful, hold down the Ctrl key, press the F key, and then let both go. In future, when I indicate Ctrl+F that's what I mean you should do.
eichsted ttysb Dec 3 23:21 (pc1) sweett ttysc Dec 3 22:40 (dov) wellman ttysd Dec 3 23:01 (dov) tuttleno ttyse Dec 3 23:03 (indyvax) wu ttysf Dec 3 23:10 (term01) daurismj ttysg Dec 3 23:10 (dov) cs414 ttysh Dec 3 23:12 (xds) cq ttysi Dec 3 23:13 (expert) cdemmert ttysk Dec 3 22:37 (xsun22) jrlee ttysn Dec 3 22:53 (mac1) fitzgejs ttyso Dec 3 23:18 (dov) doerrhb ttysp Dec 3 23:20 (dov) cdemmert ttysq Dec 3 23:00 (xsun22) frazierw ttysr Dec 3 23:01 (dov) buckeye ttyss Dec 3 23:20 (mac2) mtaylor ttyst Dec 3 23:22 (dov) look ttysu Dec 3 23:12 (age) janitor ttysw Dec 3 18:29 (age) ajones ttysx Dec 3 23:23 (rass) ~ ~ ~ ~
Notice that the entire screen was rewritten, and that the familiar tilde characters have popped up again to indicate the end of the file.
By default, vi has a two-line overlap when you move from screen to screen. If you look carefully, you can see that both eichsted and sweett show up on both screens of data. This doesn't mean that they appear twice in the file; rather, vi is trying to
help you not get lost while you wander through the file.
Now, what do you think will happen if you press Ctrl+U?
leungtc ttys0 Nov 28 15:11 (gold) chinese ttys2 Dec 3 22:53 (excalibur) cdemmert ttys5 Dec 3 23:00 (mentor) yuenca ttys6 Dec 3 23:00 (mentor) janitor ttys7 Dec 3 18:18 (age) mathisbp ttys8 Dec 3 23:17 (dov) janitor ttys9 Dec 3 18:18 (age) cs541 ttysC Dec 2 15:16 (solaria) yansong ttysL Dec 1 14:44 (math) mdps ttysO Nov 30 19:39 (localhost) md ttysU Dec 2 08:45 (muller) jac ttysa Dec 3 18:18 (localhost) eichsted ttysb Dec 3 23:21 (pc1) sweett ttysc Dec 3 22:40 (dov) wellman ttysd Dec 3 23:01 (dov) tuttleno ttyse Dec 3 23:03 (indyvax) wu ttysf Dec 3 23:10 (term01) daurismj ttysg Dec 3 23:10 (dov) cs414 ttysh Dec 3 23:12 (xds) cq ttysi Dec 3 23:13 (expert) cdemmert ttysk Dec 3 22:37 (xsun22) jrlee ttysn Dec 3 22:53 (mac1) fitzgejs ttyso Dec 3 23:18 (dov)
The command has moved you up half a screen. Notice where eichsted and sweett are now. Instead of the text being replaced at once, as when you used Ctrl+F, the text was scrolled downward a line at a time, each new line being added as the program went
along. The Ctrl+U command might work either wayone line or an entire screen at a timefor you.
Now it's time to try moving around in this file word by word. Find the w key on your keyboard and press it once to see what happens.
leungtc ttys0 Nov 28 15:11 (gold) chinese ttys2 Dec 3 22:53 (excalibur) cdemmert ttys5 Dec 3 23:00 (mentor)
Now press w six times more, noting that the cursor stops three times in the field to indicate what time the user logged into the system (15:11 in this listing). Now your cursor should be sitting on the parenthesized field:
leungtc ttys0 Nov 28 15:11 (gold) chinese ttys2 Dec 3 22:53 (excalibur) cdemmert ttys5 Dec 3 23:00 (mentor)
It's time to move backward. Press b a few times; your cursor moves backward to the beginning of each word.
What happens if you try to move backward but you're already on the first word of the line, or you try to move forward but you're already on the last word?
Using the various keys you've learned, move back to the beginning of the line beginning with leungtc, which you used in the last exercise:
leungtc ttys0 Nov 28 15:11 (gold) chinese ttys2 Dec 3 22:53 (excalibur) cdemmert ttys5 Dec 3 23:00 (mentor)
This time press the uppercase letter W, rather than the lowercase w, to move through this line. Can you see the difference? Notice what happens when you hit the time field and the parenthesized words. Instead of pressing w seven times to move to the
left parenthesis before gold, you can press W just five times.
Try moving backward using the B command. Notice that the B command differs from the b command the same way the W command differs from the w command.
Moving about forward and backward word by word, being able to move half screens or full screens at a time, and being able to zero in on specific spots with the h, j, k, and l cursor-motion keys give you quite a range of motion. Practice using these
commands in various combinations to move your cursor to specific characters in your sample file.
Being able to move around in a file is useful. The real function of an editor, however, is to enable you to easily add and removein editor parlance, insert and deleteinformation. The vi editor has a special insert mode, which you must use in
order to add to the contents of the file. There are four different ways to shift into insert mode, and you will learn about all of them in this section.
The first way to switch to insert mode is to enter the letter i, which, mnemonically enough, inserts text into the file. The other commands that accomplish more or less the same thing are a, which appends text to the file; o, which opens up a line below
the current line; and O, which opens up a line above the current line.
This time you want to start with a clean file, so quit from the big.output editing session and start vi again, this time specifying a nonexistent file called buckaroo:
% vi buckaroo ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ "buckaroo" [New file]
Notice that vi reminds you that this file doesn't exist; the bottom of the screen says New file instead of indicating the number of lines and characters.
Now it's time to try using insert mode. Press k once:
~ ~ ~ ~
The system beeps at you because you haven't moved into insert mode yet, and k still has its command meaning of moving down a line (and of course, there isn't another line yet).
Press the i key to move into insert mode, and then press the k key again:
k_ ~ ~ ~
There you go! You've added a character to the file.
Press the Backspace key, which will move the cursor over the letter k:
k ~ ~ ~
Now see what happens when you press Esc to leave insert mode and return to the vi command mode:
~ ~ ~ ~
Notice that the k vanished when you pressed Esc. That's because vi only saves text you've entered to the left of or above the cursor, not the letter the cursor is resting on.
Now move back into insert mode by pressing i and enter a few sentences from a favorite book of mine:
"He's not even here," went the conservation. "Banzai." "Where is he?" "At a hotpsial in El paso." "What? Why werent' we informed? What's wrong with him?"_ ~ ~
I've deliberately left some typing errors in the text here. Fixing them will demonstrate some important features of the vi editor. If you fixed them as you went along, that's okay, and if you added errors of your own, that's okay, too!
Press Esc to leave insert mode. Press Esc a second time to ensure that it worked; remember that vi beeps to remind you that you're already in command mode.
Now use the cursor motion keys (h, j, k, and l) to move the cursor to any point on the first line:
"He's not even here," went the conservation. "Banzai." "Where is he?" "At the hotpsial in El paso." "What? Why werent' we informed? What's wrong with him?" ~ ~
It turns out that there's a line of dialogue missing between the line you're on and "Banzai." One way to enter the line would be to move to the beginning of the line "Banzai.", insert the new text, and press Enter before pressing Esc
to quit insert mode. But vi has a special commandoto open a line immediately below the current line for inserting text. Press o on your keyboard and follow along:
"He's not even here," went the conservation. _ "Banzai." "Where is he?" "At the hotpsial in El paso." "What? Why werent' we informed? What's wrong with him?" ~ ~
Now type the missing text:
"He's not even here," went the conservation. "Who?"_ "Banzai." "Where is he?" "At the hotpsial in El paso." "What? Why werent' we informed? What's wrong with him?" ~ ~
That's it. Press Esc to return to command mode.
The problem with the snippet of dialogue you're using is that there's no way to figure out who is talking. Adding a line above this dialogue helps identify the speakers. Again, use cursor motion keys to place the cursor on the top line:
"He's not _even here," went the conservation. "Banzai." "Where is he?" "At the hotpsial in El paso." "What? Why werent' we informed? What's wrong with him?" ~ ~
Now you face a dilemma. You want to open up a line for new text, but you want the line to be above the current line, not below it. It happens that vi can do that, too. Instead of using the o command, use its big brother O instead. When you press O,
here's what you see:
_ "He's not even here," went the conservation. "Banzai." "Where is he?" "At the hotpsial in El paso." "What? Why werent' we informed? What's wrong with him?" ~ ~
Type the new sentence and press Esc.
I found myself stealing a peek at my own watch and overhead General Catbird's aide give him the latest._ "He's not even here," went the conservation. "Banzai." "Where is he?" "At the hotpsial in El paso." "What? Why werent' we informed? What's wrong with him?" ~ ~
Now the dialogue makes a bit more sense. The conversation, overheard by the narrator, takes place between the general and his aide.
There are a few words missing in one of the lines, so the next task is to insert them. Use the cursor keys to move the cursor to the fifth line, just after the word "Where":
I found myself stealing a peek at my own watch and overhead General Catbird's aide give him the latest. "He's not even here," went the conservation. "Banzai." "Where_is he?" "At the hotpsial in El paso." "What? Why werent' we informed? What's wrong with him?" ~ ~
At this juncture, you need to add the words "the hell" to make the sentence a bit stronger (and correct). You can use i to insert the text, but then you end up with a trailing space. Instead, you can add text immediately after the current
cursor location by using the a key to append the information. When you press a, the cursor moves one character to the right:
I found myself stealing a peek at my own watch and overhead General Catbird's aide give him the latest. "He's not even here," went the conservation. "Banzai." "Where is he?" "At the hotpsial in El paso." "What? Why werent' we informed? What's wrong with him?" ~ ~
Here's where vi can be difficult to use. You're in insert mode, but there's no way for you to know that. When you type the letters you want to add, the screen shows that they are appended. But what if you think you're in insert mode when you're actually
in command mode? One trick you could use to ensure you're in insert mode is to press the command key a second time. If the letter "a" shows up in the text, simply backspace over it; now you know that you're in append mode. When you're done
entering the new characters, and you're still in append mode, here's what your screen looks like:
I found myself stealing a peek at my own watch and overhead General Catbird's aide give him the latest. "He's not even here," went the conservation. "Banzai." "Where the hell is he?" "At the hotpsial in El paso." "What? Why werent' we informed? What's wrong with him?" ~ ~
Notice that the cursor stayed on the "i" in "is" throughout this operation. Press Esc to return to command mode. Notice that the cursor finally hops off the "i" and moves left one character.
To differentiate between the i and a commands, remember that the insert command always adds the new information immediately before the cursor, whereas append adds the information immediately after the cursor.
With this in mind, try to fix the apostrophe problem in the word "werent'" on the last line. Move the cursor to the "n" in that word:
"Where the hell is he?" "At the hotpsial in El paso." "What? Why werent' we informed? What's wrong with him?" ~
Now, to put the apostrophe immediately after the current character, do you want to use the insert command (i) or the append command? If you said "Append," give yourself a pat on the back! Press a to append the apostrophe:
"Where the hell is he?" "At the hotpsial in El paso." "What? Why werent' we informed? What's wrong with him?" ~
Press the ' key once and press Esc.
Quit vi. Use :q, and the program reminds you that you haven't saved your changes to this new file:
~ ~ No write since last change (:quit! overrides)
To write the changes, you need a new command, so I'll give you a preview of a set of colon commands you will learn later in this chapter. Type : (the colon character), which moves the cursor to the bottom of the screen.
~ ~ :_
Now press w to write out the file, and then press the Enter key:
~ ~ "buckaroo" 8 lines, 271 characters
It's okay to leave vi now. Use :q to quit and you're safely back at the command prompt. A quick cat confirms that the tildes were not included in the file itself:
% % cat buckaroo I found myself stealing a peek at my own watch and overhead General Catbird's aide give him the latest. "He's not even here," went the conservation. "Banzai." "Where the hell is he?" "At the hotpsial in El paso." "What? Why weren't' we informed? What's wrong with him?" %
As you can tell, the vi editor is quite powerful, and it has a plethora of commands. Just moving about and inserting text, you have learned 24 commands, as summarized in Table 7.1.
Command |
Meaning |
|
0 |
Move to beginning of line. |
|
$ |
Move to end of line. |
|
a |
Append textmove into insert mode after the current character. |
|
^b |
Back up one screen of text. |
|
B |
Back up one space-delimited word. |
|
b |
Back up one word. |
|
Backspace |
Move left one character. |
|
^d |
Move down half a page. |
|
Esc |
Leave insert mode, return to command mode. |
|
^f |
Move forward one screen of text. |
|
h |
Move left one character. |
|
i |
Insert textmove into insert mode before the current character. |
|
j |
Move down one line. |
|
k |
Move up one line. |
|
l |
Move right one character. |
|
O |
Open new line for insert above the current line. |
|
o |
Open new line for insert below the current line. |
|
Enter |
Move to beginning of next line. |
|
^u |
Move up half a page. |
|
W |
Move forward one space-delimited word. |
|
w |
Move forward one word. |
|
:w |
Write the edit buffer to the system. |
|
:q |
Quit vi and return to the UNIX prompt. |
|
:q! |
Quit vi and return to the system, throwing away any changes made to the file. |
You've already learned quite a few commands, but you've barely scratched the surface of the powerful vi command!
You now have many of the pieces you need to work efficiently with the vi editor, to zip to any point in the file, or to add text wherever you like. Now you need to learn how to delete characters, words, and lines.
The simplest form of the delete command is the x command, which functions as though you are writing an X over a letter you don't want on a printed page: it deletes the character under the cursor. Press x five times and you delete five characters.
Deleting a line of text this way can be quite tedious, so vi has some alternate commands. (Are you surprised?) One command that many vi users don't know about is the D, or delete through end of line, command. Wherever you are on a line, pressing D
immediately deletes everything after the cursor to the end of that line of text.
If there's an uppercase D command, you can just bet there's a lowercase d command too. The d command is the first of a set of more sophisticated vi commands, which are followed by a second command that indicates what you'd like to do with the command.
You already know that w and W move you forward a word in the file; they're known as addressing commands in vi. You can follow d with one of these addressing commands to specify what you would like to delete. For example, to delete a line, simply press dd.
Sometimes you might get a bit overzealous and delete more than you anticipated. That's not a problemwell, not too much of a problembecause vi remembers the state of the file prior to the most recent action taken. To undo a deletion (or
insertion, for that matter), use the u command. To undo a line of changes, use the U command. Be aware that once you've moved off the line in question, the U command is unable to restore it!
Start vi again with the big.output file you used earlier:
leungtc ttyrV Dec 1 18:27 (magenta) tuyinhwa ttyrX Dec 3 22:38 (expert) hollenst ttyrZ Dec 3 22:14 (dov) brandt ttyrb Nov 28 23:03 (age) holmes ttyrj Dec 3 21:59 (age) yuxi ttyrn Dec 1 14:19 (pc) frodo ttyro Dec 3 22:01 (mentor) labeck ttyrt Dec 3 22:02 (dov) chenlx2 ttyru Dec 3 21:53 (mentor) leungtc ttys0 Nov 28 15:11 (gold) chinese ttys2 Dec 3 22:53 (excalibur) cdemmert ttys5 Dec 3 23:00 (mentor) yuenca ttys6 Dec 3 23:00 (mentor) janitor ttys7 Dec 3 18:18 (age) mathisbp ttys8 Dec 3 23:17 (dov) janitor ttys9 Dec 3 18:18 (age) cs541 ttysC Dec 2 15:16 (solaria) yansong ttysL Dec 1 14:44 (math) mdps ttysO Nov 30 19:39 (localhost) md ttysU Dec 2 08:45 (muller) jac ttysa Dec 3 18:18 (localhost) eichsted ttysb Dec 3 23:21 (pc1) sweett ttysc Dec 3 22:40 (dov) "big.output" 40 lines, 1659 characters
Press the x key a few times to delete a few characters from the beginning of the file:
gtc ttyrV Dec 1 18:27 (magenta) tuyinhwa ttyrX Dec 3 22:38 (expert) hollenst ttyrZ Dec 3 22:14 (dov) brandt ttyrb Nov 28 23:03 (age) holmes ttyrj Dec 3 21:59 (age)
Now press u to undo the last deletion:
ngtc ttyrV Dec 1 18:27 (magenta) tuyinhwa ttyrX Dec 3 22:38 (expert) hollenst ttyrZ Dec 3 22:14 (dov) brandt ttyrb Nov 28 23:03 (age) holmes ttyrj Dec 3 21:59 (age)
If you press u again, what do you think will happen?
gtc ttyrV Dec 1 18:27 (magenta) tuyinhwa ttyrX Dec 3 22:38 (expert) hollenst ttyrZ Dec 3 22:14 (dov) brandt ttyrb Nov 28 23:03 (age) holmes ttyrj Dec 3 21:59 (age)
The undo command alternates between the last command having happened or not having happened. To explain it a bit better, the undo command is an action unto itself, so the second time you press u, you're undoing the undo command that you just requested.
Press the u key a few more times if you need to convince yourself that this is the case.
It's time to make some bigger changes to the file. Press dw twice to delete the current word and the next word in the file. It should look something like this after the first dw:
ttyrV Dec 1 18:27 (magenta) tuyinhwa ttyrX Dec 3 22:38 (expert) hollenst ttyrZ Dec 3 22:14 (dov) brandt ttyrb Nov 28 23:03 (age) holmes ttyrj Dec 3 21:59 (age)
Then it should look like this after the second dw:
Dec 1 18:27 (magenta) tuyinhwa ttyrX Dec 3 22:38 (expert) hollenst ttyrZ Dec 3 22:14 (dov) brandt ttyrb Nov 28 23:03 (age) holmes ttyrj Dec 3 21:59 (age)
Press u. You see that you can only undo the most recent command. At this point, though, because you haven't moved from the line you're editing, the U, or undo a line of changes, command will restore the line to its original splendor:
leungtc ttyrV Dec 1 18:27 (magenta) tuyinhwa ttyrX Dec 3 22:38 (expert) hollenst ttyrZ Dec 3 22:14 (dov) brandt ttyrb Nov 28 23:03 (age) holmes ttyrj Dec 3 21:59 (age)
Well, in the end, you really don't want to see some of these folk. Fortunately, you can delete lines with the dd command. What if I want to delete the entries for chinese and janitor, both of which are visible on this screen?
The first step is to use the cursor keys to move down to any place on the line for the chinese account, about halfway down the screen:
chenlx2 ttyru Dec 3 21:53 (mentor) leungtc ttys0 Nov 28 15:11 (gold) chinese ttys2 Dec 3 22:53 (excalibur) cdemmert ttys5 Dec 3 23:00 (mentor) yuenca ttys6 Dec 3 23:00 (mentor) janitor ttys7 Dec 3 18:18 (age) mathisbp ttys8 Dec 3 23:17 (dov)
If your cursor isn't somewhere in the middle of this line, move it so that you too are not at an edge.
Instead of removing this line completely, perhaps you'd rather just remove the date, time, and name of the system (in parentheses) instead. To accomplish this, you don't need to press dw a bunch of times, or even x a lot of times, but rather just D to
delete through the end of the line:
chenlx2 ttyru Dec 3 21:53 (mentor) leungtc ttys0 Nov 28 15:11 (gold) chinese ttys2 _ cdemmert ttys5 Dec 3 23:00 (mentor) yuenca ttys6 Dec 3 23:00 (mentor) janitor ttys7 Dec 3 18:18 (age) mathisbp ttys8 Dec 3 23:17 (dov)
Oh, that's not quite what you wanted to do. No problem, the undo command can fix it. Simply pressing the u key restores the text you deleted:
chenlx2 ttyru Dec 3 21:53 (mentor) leungtc ttys0 Nov 28 15:11 (gold) chinese ttys2 Dec 3 22:53 (excalibur) cdemmert ttys5 Dec 3 23:00 (mentor) yuenca ttys6 Dec 3 23:00 (mentor) janitor ttys7 Dec 3 18:18 (age) mathisbp ttys8 Dec 3 23:17 (dov)
The problem is that you used the wrong command to delete the two entries chinese and janitor from the file. Instead of using the D command, you should use dd. Pressing dd once has these results:
Dec 1 18:27 (magenta) tuyinhwa ttyrX Dec 3 22:38 (expert) hollenst ttyrZ Dec 3 22:14 (dov) brandt ttyrb Nov 28 23:03 (age) holmes ttyrj Dec 3 21:59 (age) yuxi ttyrn Dec 1 14:19 (pc) frodo ttyro Dec 3 22:01 (mentor) labeck ttyrt Dec 3 22:02 (dov) chenlx2 ttyru Dec 3 21:53 (mentor) leungtc ttys0 Nov 28 15:11 (gold) cdemmert ttys5 Dec 3 23:00 (mentor) yuenca ttys6 Dec 3 23:00 (mentor) janitor ttys7 Dec 3 18:18 (age) mathisbp ttys8 Dec 3 23:17 (dov) janitor ttys9 Dec 3 18:18 (age) cs541 ttysC Dec 2 15:16 (solaria) yansong ttysL Dec 1 14:44 (math) mdps ttysO Nov 30 19:39 (localhost) md ttysU Dec 2 08:45 (muller) jac ttysa Dec 3 18:18 (localhost) eichsted ttysb Dec 3 23:21 (pc1) sweett ttysc Dec 3 22:40 (dov) wellman ttysd Dec 3 23:01 (dov)
Notice that a new line of information has been pulled onto the screen at the bottom to replace the blank line that you removed. If you try using the u command now, what happens? You're almost done. A few presses of the Enter key and you're down to the
entry for the janitor account. Using dd removes that line too:
Dec 1 18:27 (magenta) tuyinhwa ttyrX Dec 3 22:38 (expert) hollenst ttyrZ Dec 3 22:14 (dov) brandt ttyrb Nov 28 23:03 (age) holmes ttyrj Dec 3 21:59 (age) yuxi ttyrn Dec 1 14:19 (pc) frodo ttyro Dec 3 22:01 (mentor) labeck ttyrt Dec 3 22:02 (dov) chenlx2 ttyru Dec 3 21:53 (mentor) leungtc ttys0 Nov 28 15:11 (gold) cdemmert ttys5 Dec 3 23:00 (mentor) yuenca ttys6 Dec 3 23:00 (mentor) mathisbp ttys8 Dec 3 23:17 (dov) janitor ttys9 Dec 3 18:18 (age) cs541 ttysC Dec 2 15:16 (solaria) yansong ttysL Dec 1 14:44 (math) mdps ttysO Nov 30 19:39 (localhost) md ttysU Dec 2 08:45 (muller) jac ttysa Dec 3 18:18 (localhost) eichsted ttysb Dec 3 23:21 (pc1) sweett ttysc Dec 3 22:40 (dov) wellman ttysd Dec 3 23:01 (dov) tuttleno ttyse Dec 3 23:03 (indyvax)
Each line below the one deleted moves up a line to fill in the blank space, and a new line, for tuttleno, moves up from the following screen.
Now you want to return to the buckaroo file to remedy some of the horrendous typographic errors! It doesn't matter whether you save the changes you've just made to the file, so use :q! to quit, discarding these edit changes to the big.output file.
Entering vi buckaroo starts vi again:
I found myself stealing a peek at my own watch and overhead General Catbird's aide give him the latest. "He's not even here," went the conservation. "Banzai." "Where the hell is he?" "At the hotpsial in El paso." "What? Why weren't' we informed? What's wrong with him?" ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ "buckaroo" 8 lines, 271 characters
There are a few fixes you can make in short order. The first is to change "conservation" to "conversation" on the third line. To move there, press the Return key twice and then use W to zip forward until the cursor is at the first
letter of the word you're editing:
I found myself stealing a peek at my own watch and overhead General Catbird's aide give him the latest. "He's not even here," went the conservation. "Banzai." "Where the hell is he?"
Then use the dw command:
I found myself stealing a peek at my own watch and overhead General Catbird's aide give him the latest. "He's not even here," went the . "Banzai." "Where the hell is he?"
Now enter insert mode by pressing i and type in the correct spelling of the word "conversation." Then press Esc:
I found myself stealing a peek at my own watch and overhead General Catbird's aide give him the latest. "He's not even here," went the conversation. "Banzai." "Where the hell is he?"
That's one fix. Now move down a few lines to fix the atrocious misspelling of "hospital":
"Banzai." "Where the hell is he?" "At the hotpsial in El paso." "What? Why weren't' we informed? What's wrong with him?" ~
Again, use dw to delete the word, then i to enter insert mode. Type "hospital" and press Esc, and all is well on the line:
"Banzai." "Where the hell is he?" "At the hospital in El paso." "What? Why weren't' we informed? What's wrong with him?" ~
Well, almost all is well. The first letter of "Paso" needs to be capitalized. Move to it by pressing w:
"Banzai." "Where the hell is he?" "At the hospital in El paso." "What? Why weren't' we informed? What's wrong with him?" ~
It's time for a secret vi expert command! Instead of pressing x to delete the letter, i to enter insert mode, P as the correct letter, and Esc to return to command mode, there's a much faster way to transpose case: the ~ command. Press the ~ character
once, and here's what happens:
"Banzai." "Where the hell is he?" "At the hospital in El Paso." "What? Why weren't' we informed? What's wrong with him?" ~
Cool, isn't it? Back up to the beginning of the word again, using the h command, and press ~ a few times to see what happens. Notice that each time you press ~, the character's case switches (transposes) and the cursor moves to the next character. Press
~ four times and you should end up with this:
"Banzai." "Where the hell is he?" "At the hospital in El pASO." "What? Why weren't' we informed? What's wrong with him?" ~
Back up to the beginning of the word and press ~ four more times until the word is correct.
One more slight change and the file is fixed! Move to the last line of the file, to the extra apostrophe in the word "weren't'," and use the x key to delete the offending character. The screen should now look like this:
I found myself stealing a peek at my own watch and overhead General Catbird's aide give him the latest. "He's not even here," went the conversation. "Banzai." "Where the hell is he?" "At the hospital in El Paso." "What? Why weren't we informed? What's wrong with him?" ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
That looks great! It's time to save it for posterity. Use :wq, a shortcut that has vi write out the changes, and then immediately quit the program:
~ ~ ~ "buckaroo" 8 lines, 270 characters %
Not only have you learned about the variety of deletion options in vi, but you have also learned a few simple shortcut commands: ~, which transposes case, and :wq, which writes out the changes and quits the program all in one step.
You should feel pleased; you're now a productive and knowledgeable vi user, and you can modify files, making easy or tough changes. Go back to your system and experiment further, modifying some of the other files. Be careful, though, not to make changes
in any of your dot files (for example, .cshrc), lest you cause trouble that would be difficult to fix!
With the addition of two more capabilities, you'll be ready to face down any vi expert, demonstrating your skill and knowledge of the editor. Much more importantly, you'll be able to really fly through files, moving immediately to the information you
desire.
The two new capabilities are for finding specific words or phrases in a file and for moving to specific lines in a file. Similar to searching for patterns in more and page, /pattern searches forward in the file for a specified pattern, and
?pattern searches backward for the specified pattern. To repeat the previous search, use the n command to tell vi to search again, in the same direction, for the same pattern.
You can easily move to any specific line in a file using the G, or go to line, command. If you press a number before you press G, the cursor will move to that line in the file. If you press G without a line number, the cursor will zip you to the very
last line of the file by default.
Start vi again with the big.output file:
leungtc ttyrV Dec 1 18:27 (magenta) tuyinhwa ttyrX Dec 3 22:38 (expert) hollenst ttyrZ Dec 3 22:14 (dov) brandt ttyrb Nov 28 23:03 (age) holmes ttyrj Dec 3 21:59 (age) yuxi ttyrn Dec 1 14:19 (pc) frodo ttyro Dec 3 22:01 (mentor) labeck ttyrt Dec 3 22:02 (dov) chenlx2 ttyru Dec 3 21:53 (mentor) leungtc ttys0 Nov 28 15:11 (gold) chinese ttys2 Dec 3 22:53 (excalibur) cdemmert ttys5 Dec 3 23:00 (mentor) yuenca ttys6 Dec 3 23:00 (mentor) janitor ttys7 Dec 3 18:18 (age) mathisbp ttys8 Dec 3 23:17 (dov) janitor ttys9 Dec 3 18:18 (age) cs541 ttysC Dec 2 15:16 (solaria) yansong ttysL Dec 1 14:44 (math) mdps ttysO Nov 30 19:39 (localhost) md ttysU Dec 2 08:45 (muller) jac ttysa Dec 3 18:18 (localhost) eichsted ttysb Dec 3 23:21 (pc1) sweett ttysc Dec 3 22:40 (dov) "big.output" 40 lines, 1659 characters
Remember that you used :q! to quit earlier, so your changes were not retained.
To move to the very last line of the file, press G once:
cdemmert ttysk Dec 3 22:37 (xsun) jrlee ttysn Dec 3 22:53 (mac1) fitzgejs ttyso Dec 3 23:18 (dov) doerrhb ttysp Dec 3 23:20 (dov) cdemmert ttysq Dec 3 23:00 (xsun) frazierw ttysr Dec 3 23:01 (dov) buckeye ttyss Dec 3 23:20 (mac2) mtaylor ttyst Dec 3 23:22 (dov) look ttysu Dec 3 23:12 (age) janitor ttysw Dec 3 18:29 (age) ajones ttysx Dec 3 23:23 (rassilon) ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
To move to the third line of the file, press 3 followed by G:
leungtc ttyrV Dec 1 18:27 (magenta) tuyinhwa ttyrX Dec 3 22:38 (expert) hollenst ttyrZ Dec 3 22:14 (dov) brandt ttyrb Nov 28 23:03 (age) holmes ttyrj Dec 3 21:59 (age) yuxi ttyrn Dec 1 14:19 (pc) frodo ttyro Dec 3 22:01 (mentor) labeck ttyrt Dec 3 22:02 (dov) chenlx2 ttyru Dec 3 21:53 (mentor) leungtc ttys0 Nov 28 15:11 (gold) chinese ttys2 Dec 3 22:53 (excalibur) cdemmert ttys5 Dec 3 23:00 (mentor) yuenca ttys6 Dec 3 23:00 (mentor) janitor ttys7 Dec 3 18:18 (age) mathisbp ttys8 Dec 3 23:17 (dov) janitor ttys9 Dec 3 18:18 (age) cs541 ttysC Dec 2 15:16 (solaria) yansong ttysL Dec 1 14:44 (math) mdps ttysO Nov 30 19:39 (localhost) md ttysU Dec 2 08:45 (muller) jac ttysa Dec 3 18:18 (localhost) eichsted ttysb Dec 3 23:21 (pc1) sweett ttysc Dec 3 22:40 (dov)
Notice that the cursor is on the third line of the file.
Now it's time to search. From your previous travels in this file, you know that the very last line is for the account ajones, but instead of using G to move there directly, you can search for the specified pattern by using the / search command.
Pressing / immediately moves the cursor to the bottom of the screen:
md ttysU Dec 2 08:45 (mueller) jac ttysa Dec 3 18:18 (localhost) eichsted ttysb Dec 3 23:21 (pc1) sweett ttysc Dec 3 22:40 (dov) /_
Now you can type in the pattern ajones:
md ttysU Dec 2 08:45 (mueller) jac ttysa Dec 3 18:18 (localhost) eichsted ttysb Dec 3 23:21 (pc1) sweett ttysc Dec 3 22:40 (dov) /ajones_
When you press Return, vi spins through the file and moves you to the first line it finds that contains the specified pattern:
cdemmert ttysk Dec 3 22:37 (xsun) jrlee ttysn Dec 3 22:53 (mac1) fitzgejs ttyso Dec 3 23:18 (dov) doerrhb ttysp Dec 3 23:20 (dov) cdemmert ttysq Dec 3 23:00 (xsun) frazierw ttysr Dec 3 23:01 (dov) buckeye ttyss Dec 3 23:20 (mac2) mtaylor ttyst Dec 3 23:22 (dov) look ttysu Dec 3 23:12 (age) janitor ttysw Dec 3 18:29 (age) ajones ttysx Dec 3 23:23 (rassilon) ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
If you press n to search for this pattern again, a slash appears at the very bottom line to show that vi understood your request. But the cursor stays exactly where it is, which indicates that this is the only occurrence of the pattern in this file.
You notice that the account janitor has all sorts of sessions running. To search backward for occurrences of their account, use the ? command:
~ ~ ?janitor_
The first search moves the cursor up one line, which leaves the screen looking almost the same:
cdemmert ttysk Dec 3 22:37 (xsun) jrlee ttysn Dec 3 22:53 (mac1) fitzgejs ttyso Dec 3 23:18 (dov) doerrhb ttysp Dec 3 23:20 (dov) cdemmert ttysq Dec 3 23:00 (xsun) frazierw ttysr Dec 3 23:01 (dov) buckeye ttyss Dec 3 23:20 (mac2) mtaylor ttyst Dec 3 23:22 (dov) look ttysu Dec 3 23:12 (age) janitor ttysw Dec 3 18:29 (age) ajones ttysx Dec 3 23:23 (rassilon) ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ?janitor
Here's where n, or next search, can come in handy. If you press n this time and there is another occurrence of the pattern in the file, vi moves you directly to the match:
yuxi ttyrn Dec 1 14:19 (pc) frodo ttyro Dec 3 22:01 (mentor) labeck ttyrt Dec 3 22:02 (dov) chenlx2 ttyru Dec 3 21:53 (mentor) leungtc ttys0 Nov 28 15:11 (gold) chinese ttys2 Dec 3 22:53 (excalibur) cdemmert ttys5 Dec 3 23:00 (mentor) yuenca ttys6 Dec 3 23:00 (mentor) janitor ttys7 Dec 3 18:18 (age) mathisbp ttys8 Dec 3 23:17 (dov) janitor ttys9 Dec 3 18:18 (age) cs541 ttysC Dec 2 15:16 (solaria) yansong ttysL Dec 1 14:44 (math) mdps ttysO Nov 30 19:39 (localhost) md ttysU Dec 2 08:45 (muller) jac ttysa Dec 3 18:18 (localhost) eichsted ttysb Dec 3 23:21 (pc1) sweett ttysc Dec 3 22:40 (dov) wellman ttysd Dec 3 23:01 (dov) tuttleno ttyse Dec 3 23:03 (indyvax) wu ttysf Dec 3 23:10 (term01) daurismj ttysg Dec 3 23:10 (dov) cs414 ttysh Dec 3 23:12 (xds)
When you're done, quit vi by using :q.
There are not dozens, but hundreds of commands in vi. Rather than overwhelm you with all of them, even in a table, I have opted instead to work with the most basic and important commands.
The vi command wouldn't be part of UNIX if it didn't have some startup options available, but there really are only two worth mentioning. The -R flag sets up vi as a read-only file to ensure that you don't accidentally modify a file. The second option
doesn't start with a hyphen, but with a plus sign: any command following the plus sign is used as an initial command to the program. This is more useful than it may sound. The command vi +$ sample, for example, starts the editor at the bottom of the file
sample, and vi +17 sample starts the editor on the 17th line of sample.
First, this is the read-only format:
% vi -R buckaroo I found myself stealing a peek at my own watch and overhead General Catbird's aide give him the latest. "He's not even here," went the conversation. "Banzai." "Where the hell is he?" "At the hospital in El Paso." "What? Why weren't we informed? What's wrong with him?" ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ "buckaroo" [Read only] 8 lines, 270 characters
Notice the addition of the [Read only] message on the status line. You can edit the file, but if you try to save the edits with :w, you will see this:
~ ~ "buckaroo" File is read only
Quit vi with :q!.
Next, recall that janitor occurs in many places in the big.output file. Start vi on the file line that contains the pattern janitor in the file:
% vi +/janitor big.output brandt ttyrb Nov 28 23:03 (age) holmes ttyrj Dec 3 21:59 (age) yuxi ttyrn Dec 1 14:19 (pc) frodo ttyro Dec 3 22:01 (mentor) labeck ttyrt Dec 3 22:02 (dov) chenlx2 ttyru Dec 3 21:53 (mentor) leungtc ttys0 Nov 28 15:11 (gold) chinese ttys2 Dec 3 22:53 (excalibur) cdemmert ttys5 Dec 3 23:00 (mentor) yuenca ttys6 Dec 3 23:00 (mentor) janitor ttys7 Dec 3 18:18 (age) mathisbp ttys8 Dec 3 23:17 (dov) janitor ttys9 Dec 3 18:18 (age) cs541 ttysC Dec 2 15:16 (solaria) yansong ttysL Dec 1 14:44 (math) mdps ttysO Nov 30 19:39 (localhost) md ttysU Dec 2 08:45 (muller) jac ttysa Dec 3 18:18 (localhost) eichsted ttysb Dec 3 23:21 (pc1) sweett ttysc Dec 3 22:40 (dov) wellman ttysd Dec 3 23:01 (dov) tuttleno ttyse Dec 3 23:03 (indyvax) wu ttysf Dec 3 23:10 (term01) "big.output" 40 lines, 1659 characters
This time notice where the cursor is sitting.
Finally, launch vi with the cursor on the third line of the file buckaroo:
% vi +3 buckaroo I found myself stealing a peek at my own watch and overhead General Catbird's aide give him the latest. "He's not even here," went the conversation. "Banzai." "Where the hell is he?" "At the hospital in El Paso." "What? Why weren't we informed? What's wrong with him?" ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ "buckaroo" 8 lines, 270 characters
Again, notice where the cursor rests.
At times it can be helpful to know these two starting options. In particular, I often use +/pattern to start the editor at a specific pattern, but you can use vi for years without ever knowing more than just the name of the command itself.
Without too much explanation, you have learned a few colon commands, commands that begin with a colon. The colon immediately zooms the cursor to the bottom of the screen for further input. These commands are actually a subset of quite a large range of
commands, all part of the ex editor that lives inside the vi visual interface. (That's why vi is known as an interface to an editor, rather than an editor itself.)
The colon commands that are most helpful are :w, which writes the buffer back to the system; :w filename, which writes the buffer to the specified file; :q, which quits the editor; :q!, which quits regardless of whether any changes have occurred;
:r filename, which reads another file into the editor; :e filename, which switches to the specified file; and :n, which moves to the next file in a list of files.
Start vi again, this time specifying more than one file on the command line; vi quickly indicates that you want to edit more than one file:
% vi buckaroo big.output 2 files to edit.
Then it clears the screen and shows you the first file:
I found myself stealing a peek at my own watch and overhead General Catbird's aide give him the latest. "He's not even here," went the conversation. "Banzai." "Where the hell is he?" "At the hospital in El Paso." "What? Why weren't we informed? What's wrong with him?" ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ "buckaroo" 8 lines, 270 characters
Using :w results in this:
~ ~ ~ "buckaroo" 8 lines, 270 characters
Instead, try writing to a different file, using :w newfile:
~ ~ :w newfile_
When you press Return, you see this:
~ ~ "newfile" [New file] 8 lines, 270 characters
Now pay attention to where the cursor is in the file. The :r, or read file, command always includes the contents of the file below the current line. Just before you press Return, then, here's what your screen looks like:
I found myself stealing a peek at my own watch and overhead General Catbird's aide give him the latest. "He's not even here," went the conversation. "Banzai." "Where the hell is he?" "At the hospital in El Paso." "What? Why weren't we informed? What's wrong with him?" ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ :r newfile_
Pressing Return yields this:
I found myself stealing a peek at my own watch and overhead General Catbird's I found myself stealing a peek at my own watch and overhead General Catbird's aide give him the latest. "He's not even here," went the conversation. "Banzai." "Where the hell is he?" "At the hospital in El Paso." "What? Why weren't we informed? What's wrong with him?" aide give him the latest. "He's not even here," went the conversation. "Banzai." "Where the hell is he?" "At the hospital in El Paso." "What? Why weren't we informed? What's wrong with him?" ~ ~ ~ ~ ~ ~ ~
This can be a helpful way to include one file within another, or to build a file that contains lots of other files.
Now that you've garbled the file, save it to a new file, buckaroo.confused:
~ ~ :w buckaroo.confused_
Press Return:
~ ~ "buckaroo.confused" [New file] 16 lines, 540 characters
Now it's time to move to the second file in the list of files given to vi at startup. To do this, I use the :n, or next file, command:
~ ~ :n_
Pressing Return results in the next file being brought into the editor to replace the text removed earlier:
leungtc ttyrV Dec 1 18:27 (magenta) tuyinhwa ttyrX Dec 3 22:38 (expert) hollenst ttyrZ Dec 3 22:14 (dov) brandt ttyrb Nov 28 23:03 (age) holmes ttyrj Dec 3 21:59 (age) yuxi ttyrn Dec 1 14:19 (pc) frodo ttyro Dec 3 22:01 (mentor) labeck ttyrt Dec 3 22:02 (dov) chenlx2 ttyru Dec 3 21:53 (mentor) leungtc ttys0 Nov 28 15:11 (gold) chinese ttys2 Dec 3 22:53 (excalibur) cdemmert ttys5 Dec 3 23:00 (mentor) yuenca ttys6 Dec 3 23:00 (mentor) janitor ttys7 Dec 3 18:18 (age) mathisbp ttys8 Dec 3 23:17 (dov) janitor ttys9 Dec 3 18:18 (age) cs541 ttysC Dec 2 15:16 (solaria) yansong ttysL Dec 1 14:44 (math) mdps ttysO Nov 30 19:39 (localhost) md ttysU Dec 2 08:45 (muller) jac ttysa Dec 3 18:18 (localhost) eichsted ttysb Dec 3 23:21 (pc1) sweett ttysc Dec 3 22:40 (dov) "big.output" 40 lines, 1659 characters
In the middle of working on this, you suddenly realize that you need to make a slight change to the recently saved buckaroo.confused file. That's where the :e command comes in handy. Using it, you can switch to any other file:
~ ~ :e buckaroo.confused_
Press Return:
I found myself stealing a peek at my own watch and overhead General Catbird's I found myself stealing a peek at my own watch and overhead General Catbird's aide give him the latest. "He's not even here," went the conversation. "Banzai." "Where the hell is he?" "At the hospital in El Paso." "What? Why weren't we informed? What's wrong with him?" aide give him the latest. "He's not even here," went the conversation. "Banzai." "Where the hell is he?" "At the hospital in El Paso." "What? Why weren't we informed? What's wrong with him?" ~ ~ ~ ~ ~ ~ ~ "buckaroo.confused" 16 lines, 540 characters
Table 7.2 summarizes the basic vi commands you learned in this section.
Command |
Meaning |
|
0 |
Move to beginning of line. |
|
$ |
Move to end of line. |
|
/pattern |
Search forward for the next line using a specified pattern. |
|
?pattern |
Search backward for the next line using a specified pattern. |
|
a |
Append textmove into insert mode after the current character. |
|
^b |
Back up one screen of text. |
|
B |
Back up one space-delimited word. |
|
b |
Back up one word. |
|
Backspace |
Move left one character. |
|
^d |
Move down half a page. |
|
D |
Delete through end of line. |
|
d |
Deletedw = delete word, dd = delete line. |
|
Esc |
Leave insert mode, return to command mode. |
|
^f |
Move forward one screen of text. |
|
G |
Go to the last line of the file. |
|
nG |
Go to the nth line of the file. |
|
h |
Move left one character. |
|
i |
Insert textmove into insert mode before the current character. |
|
j |
Move down one line. |
|
k |
Move up one line. |
|
l |
Move right one character. |
|
n |
Repeat last search. |
|
O |
Open new line for insert above the current line. |
|
o |
Open new line for insert below the current line. |
|
Return |
Move to beginning of next line. |
|
^u |
Move up half a page. |
|
U |
Undoreplace current line if changed. |
|
u |
Undo the last change made to the file. |
|
W |
Move forward one space-delimited word. |
|
w |
Move forward one word. |
|
x |
Delete a single character. |
|
:e file |
Edit a specified file without leaving vi. |
|
:n |
Move to the next file in the file list. |
|
:q |
Quit vi and return to the UNIX prompt. |
|
:q! |
Quit vi and return to the system, throwing away any changes made to the file. |
|
:r file |
Read the contents of a specified file, including it in the current edit buffer. |
|
:w file |
Write the contents of the buffer to a specified file. |
|
:w |
Write the edit buffer to the system. |
In the last section you learned some fifty vi commands, which enable you to easily move about in files, insert text, delete other text, search for specific patterns, and move from file to file without leaving the program. This section expands your
expertise by showing you some more powerful vi commands.
To be honest, you can do fine in vi without ever reading this section. You already know how to insert and delete text, save or quit without saving, and search for particular patterns, even from the command line as you start vi for the first time! On the
other hand, vi is like any other complex topic. The more you're willing to study and learn, the more the program will bow to your needs. This means you can accomplish a wider variety of different tasks on a daily basis.
In the last section, you fixed a variety of problems by deleting words and replacing them with new words. A much smarter way to do this is to use either the change or the replace commands.
Each command has a lowercase and uppercase version, and each is quite different from the other. The r command replaces the character that the cursor is sitting upon with the next character you type, whereas the R command puts you into replace mode, so
that anything you type overwrites whatever is already on the line. By contrast, C replaces everything on the line with whatever you type. The c change command is the most powerful of them all. It works just like the d command. You can use the c command
with any address command, and it allows you to change text through that address, whether it's a word, line, or even the rest of the document.
Start vi with the buckaroo.confused file.
I found myself stealing a peek at my own watch and overhead General Catbird's I found myself stealing a peek at my own watch and overhead General Catbird's aide give him the latest. "He's not even here," went the conversation. "Banzai." "Where the hell is he?" "At the hospital in El Paso." "What? Why weren't we informed? What's wrong with him?" aide give him the latest. "He's not even here," went the conversation. "Banzai." "Where the hell is he?" "At the hospital in El Paso." "What? Why weren't we informed? What's wrong with him?" ~ ~ ~ ~ ~ ~ "buckaroo.confused" 16 lines, 540 characters
Without moving the cursor at all, press R. Nothing happens, or so it seems. Now type the words Excerpt from "Buckaroo Banzai" and watch what happens:
Excerpt from "Buckaroo Banzai"at my own watch and overhead General Catbird's I found myself stealing a peek at my own watch and overhead General Catbird's aide give him the latest. "He's not even here," went the conversation.
Now press Esc and notice that what you see on the screen is exactly what's in the file.
This isn't, however, quite what you want. You could use either D or d$ to delete through the end of the line, but that's a bit awkward. Instead, use 0 to move back to the beginning of the line:
Excerpt from "Buckaroo Banzai" at my own watch and overhead General Catbird's I found myself stealing a peek at my own watch and overhead General Catbird's aide give him the latest. "He's not even here," went the conversation.
This time, press C to change the contents of the line. Before you even type a single character of the new text, notice what the line now looks like:
Excerpt from "Buckaroo Banzai" at my own watch and overhead General Catbird'$ I found myself stealing a peek at my own watch and overhead General Catbird's aide give him the latest. "He's not even here," went the conversation.
Here's where a subtle difference comes into play! Look at the very last character on the current line. When you pressed C, the program replaced the "s" with a "$" to show the range of the text to be changed by the command. Press the
Tab key once, and then type Excerpt from "Buckaroo Bansai" by Earl MacRauch.
Excerpt from "Buckaroo Bansai" by Earl MacRauchhead General Catbird'$ I found myself stealing a peek at my own watch and overhead General Catbird's aide give him the latest. "He's not even here," went the conversation.
This time, watch what happens when you press Esc:
Excerpt from "Buckaroo Bansai" by Earl MacRauch I found myself stealing a peek at my own watch and overhead General Catbird's aide give him the latest. "He's not even here," went the conversation.
There's another mistake. It should be Buckaroo Banzai, not Bansai. This is a chance to try the new r command.
Use cursor control keys to move the cursor to the offending letter. Use b to back up words and then h a few times to move into the middle of the word. Your screen now looks like this:
Excerpt from "Buckaroo Bansai" by Earl MacRauch I found myself stealing a peek at my own watch and overhead General Catbird's aide give him the latest. "He's not even here," went the conversation.
Now press r. Again, nothing happens; the cursor doesn't move. Press r again to make sure it worked:
Excerpt from "Buckaroo Banrai" by Earl MacRauch I found myself stealing a peek at my own watch and overhead General Catbird's aide give him the latest. "He's not even here," went the conversation.
That's no good. It replaced the "s" with an "r," which definitely isn't correct. Press rz, and you should have the following:
Excerpt from "Buckaroo Banzai" by Earl MacRauch I found myself stealing a peek at my own watch and overhead General Catbird's aide give him the latest. "He's not even here," went the conversation.
Okay, those are the easy ones. Now it's time to see what the c command can do for you. In fact, it's incredibly powerful. You can change just about any range of information from the current point in the file in either direction!
To start, move to the middle of the file, where the second copy of the passage is found:
Excerpt from "Buckaroo Banzai" by Earl MacRauch I found myself stealing a peek at my own watch and overhead General Catbird's aide give him the latest. "He's not even here," went the conversation. "Banzai." "Where the hell is he?" "At the hospital in El Paso." "What? Why weren't we informed? What's wrong with him?" aide give him the latest. "He's not even here," went the conversation. "Banzai." "Where the hell is he?" "At the hospital in El Paso." "What? Why weren't we informed? What's wrong with him?" ~ ~ ~ ~ ~ ~ ~ "buckaroo.confused" 16 lines, 540 characters
Change the word "aide" that the cursor is sitting on to "The tall beige wall clock opted to." First press c and note that, like many other commands in vi, nothing happens. Now press w to change just the first word. The screen should
look like this:
"At the hospital in El Paso." "What? Why weren't we informed? What's wrong with him?" aid$ give him the latest. "He's not even here," went the conversation. "Banzai."
Again, the program has replaced the last character of the change to a $. Now type The tall beige wall clock opted to. Once you reach the $, the editor stops overwriting characters and starts inserting them instead, so the screen now looks like this:
"At the hospital in El Paso." "What? Why weren't we informed? What's wrong with him?" The tall beige wall clock opted to_give him the latest. "He's not even here," went the conversation. "Banzai."
Press Esc and you're done (though you can undo the change with the u or U commands, of course).
Tall and beige or not, this section makes no sense now, so change this entire line using the $ motion command. First use 0 to move to the beginning of the line and then press c$:
"At the hospital in El Paso." "What? Why weren't we informed? What's wrong with him?" The tall beige wall clock opted to give him the latest$ "He's not even here," went the conversation. "Banzai."
This is working. The last character changed to the dollar sign. Press Esc, and the entire line is deleted:
"At the hospital in El Paso." "What? Why weren't we informed? What's wrong with him?" _ "He's not even here," went the conversation. "Banzai."
There are still five lines below the current line. You could delete them and then type in the information you want, but that's primitive. Instead, the c command comes to the rescue. Move down one line, press c5, and press Return. Watch what happens:
"At the hospital in El Paso." "What? Why weren't we informed? What's wrong with him?" ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ 6 lines changed
In general, you can always change the current and next line by using c followed by Return (because the Return key is a motion key too, remember). By prefacing the command with a number, you changed the range from two lines to five.
You might be asking, "Why two lines?" The answer is subtle. In essence, anytime you use the c command you change the current line plus any additional lines that might be touched by the command. Pressing Return moves the cursor to the following
line; therefore, the current line (starting at the cursor location) through the following line are changed. The command should probably just change to the beginning of the following line, but that's beyond our control!
Now press Tab four times, type in (page 8), and press the Esc key. The screen should look like this:
"Where the hell is he?"
"At the hospital in El Paso."
"What? Why weren't we informed? What's wrong with him?"
(page 8)
~
~
~
What if you change your mind? That's where the u command comes in handy. A single press of the key and the original copy is restored:
Excerpt from "Buckaroo Banzai" by Earl MacRauch I found myself stealing a peek at my own watch and overhead General Catbird's aide give him the latest. "He's not even here," went the conversation. "Banzai." "Where the hell is he?" "At the hospital in El Paso." "What? Why weren't we informed? What's wrong with him?" "He's not even here," went the conversation. "Banzai." "Where the hell is he?" "At the hospital in El Paso." "What? Why weren't we informed? What's wrong with him?" ~ ~ ~ ~ ~ ~ ~ 5 more lines
The combination of replace and change commands adds a level of sophistication to an editor you might have thought could only insert and delete. There's much more to cover, so don't stop now!
You have now seen two commands that were prefixed by a number to cause a specific action. The G command moves you to the very last line of the file, unless you type in a number first. If you type in a number, the G command moves to the specified line
number. Similarly, pressing a number and then the Return key causes vi to repeat the key the specified number of times.
Numeric repeat prefixes are actually widely available in vi, and this is the missing piece of your navigational tool set.
Move back to the top of the buckaroo.confused file. This time, use 1G to move there, rather than a bunch of k keys or other steps. The top of the screen now looks like this:
Excerpt from "Buckaroo Banzai" by Earl MacRauch I found myself stealing a peek at my own watch and overhead General Catbird's aide give him the latest. "He's not even here," went the conversation.
Now move forward 15 words. Instead of pressing w 15 times, enter 15w.
Excerpt from "Buckaroo Banzai" by Earl MacRauch I found myself stealing a peek at my own watch and overhead General Catbird's aide give him the latest. "He's not even here," went the conversation.
Now move down seven lines by pressing the 7 key followed by the Return key. Use o to give yourself a blank line and press Esc again:
"Where the hell is he?" "At the hospital in El Paso." "What? Why weren't we informed? What's wrong with him?" _ "He's not even here," went the conversation. "Banzai."
You want to put "Go Team Banzai!" on the bottom, repeated three times. Can you guess how to do it? Simply press 3i to move into insert mode, and then type Go Team Banzai!. The screen looks like this:
"Where the hell is he?" "At the hospital in El Paso." "What? Why weren't we informed? What's wrong with him?" Go Team Banzai! _ "He's not even here," went the conversation. "Banzai."
Pressing Esc has a dramatic result:
"Where the hell is he?" "At the hospital in El Paso." "What? Why weren't we informed? What's wrong with him?" Go Team Banzai! Go Team Banzai! Go Team Banzai! "He's not even here," went the conversation. "Banzai."
Now get rid of all the lines below the current line. There are many different ways to do this, but you're going to try to guess how many words are present and give dw a repeat count prefix to delete that many words. (Actually, you don't need to know the
number of words, because vi will repeat the command only while it makes sense to do so).
I press 75dw and the screen instantly looks like this:
Excerpt from "Buckaroo Banzai" by Earl MacRauch I found myself stealing a peek at my own watch and overhead General Catbird's aide give him the latest. "He's not even here," went the conversation. "Banzai." "Where the hell is he?" "At the hospital in El Paso." "What? Why weren't we informed? What's wrong with him?" Go Team Banzai! Go Team Banzai! Go Team Banzai! ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ 7 lines deleted
Try the undo command here to see what happens!
Almost all commands in vi can work with a numeric repeat prefix, even commands that you might not expect to work, such as the i insert command. Remember that a request can be accomplished in many ways. To delete five words, for example, you could use
5dw or d5w. Experiment on your own, and you'll get the idea.
It's very helpful to have an editor that works with the entire screen, but sometimes you only need to know what line you're currently on. Further, sometimes it can be very helpful to have all the lines numbered on the screen. With vi, you can do both of
thesethe former by pressing ^g (remember, that's Ctrl+G) while in command mode, and the latter by using a complex colon command, :set number, followed by Return. To turn off the display of line numbers, simply type :set nonumber and press Return.
You're still looking at buckaroo.confused in vi. The screen looks like this:
Excerpt from "Buckaroo Banzai" by Earl MacRauch I found myself stealing a peek at my own watch and overhead General Catbird's aide give him the latest. "He's not even here," went the conversation. "Banzai." "Where the hell is he?" "At the hospital in El Paso." "What? Why weren't we informed? What's wrong with him?" Go Team Banzai! Go Team Banzai! Go Team Banzai! ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ 7 lines deleted
Can you see where the cursor is? To find out what line number the cursor is on, press ^g. The information is listed on the status line at the bottom:
~ ~ ~ "buckaroo.confused" [Modified] line 10 of 11, column 1 90%
There's lots of information here. Included here is the name of the file (buckaroo.confused), an indication that vi thinks you've changed it since you started the program ([Modified]), the current line (10), total lines in the file (11), what column
you're in, and, finally, an estimate of how far into the file you are.
Eleven lines? Count the display again. There are 12 lines. What's going on? The answer will become clear if you turn on line numbering for the entire file. To do this, type :, which zips the cursor to the bottom of the screen, where you then enter the
set number command:
~ ~ ~ :set number_
Pressing Return causes the screen to change, thus:
1 Excerpt from "Buckaroo Banzai" by Earl MacRauch
2 I found myself stealing a peek at my own watch and overhead General Catbird's
3 aide give him the latest.
4 "He's not even here," went the conversation.
5 "Banzai."
6 "Where the hell is he?"
7 "At the hospital in El Paso."
8 "What? Why weren't we informed? What's wrong with him?"
9
10 Go Team Banzai! Go Team Banzai! Go Team Banzai!
11
~
~
~
~
~
~
~
~
~
~
Now you can see why vi only figures that there are 11 lines, even though it seems by the screens shown here that there are 12 lines.
To turn off the line numbering, use the opposite command, :set nonumber, followed by Return.
There are definitely times when being able to include the number of each line is helpful. One example is if you are using awk and it's complaining about a specific line being in an inappropriate format (usually by saying syntax error, bailing out! or
something similar).
Though most of vi is easy to learn and use, one command that always causes great trouble for users is the search and replace command. The key to understanding this command is to remember that there's a line editor (ex) hidden underneath vi. Instead of
trying to figure out some arcane vi command, it's easiest to just drop to the line editor and use a simple colon commandone identical to the command used in sedto replace an old pattern with a new one. To replace an existing word on the current
line with a new word (the simplest case), use :s/old/new/. If you want to have all occurrences on the current line matched, you need to add the g suffix (just as with sed): :s/old/new/g.
To change all occurrences of one word or phrase to another across the entire file, the command is identical to the preceding command, except that you must add a prefix indicating the range of lines affected. Recall that $ is the last line in the file,
and that ranges are specified (in this case, as in sed) by two numbers separated by a comma. It should be no surprise that the command is :1,$ s/old/new/g.
You're still working with the buckaroo.confused file, so your screen should look very similar to this:
Excerpt from "Buckaroo Banzai" by Earl MacRauch I found myself stealing a peek at my own watch and overhead General Catbird's aide give him the latest. "He's not even here," went the conversation. "Banzai." "Where the hell is he?" "At the hospital in El Paso." "What? Why weren't we informed? What's wrong with him?" Go Team Banzai! Go Team Banzai! Go Team Banzai! ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
The cursor is on the very first line. Rename Earl. Type :. The cursor immediately moves to the bottom. Then type s/Earl/Duke/. Pressing Return produces this:
Excerpt from "Buckaroo Banzai" by Duke MacRauch I found myself stealing a peek at my own watch and overhead General Catbird's aide give him the latest. "He's not even here," went the conversation.
As you can see, this maneuver was simple and effective.
Maybe developmental psychology is your bag. Instead of having this Banzai character, you want your fictional character to be called Bandura. You could use the previous command to change the occurrence on the current line, but you really want to change
all occurrences within the file.
This is no problem. Type :1,$ s/Banzai/Bandura/ and press Return. Here's the result:
Excerpt from "Buckaroo Bandura" by Duke MacRauch I found myself stealing a peek at my own watch and overhead General Catbird's aide give him the latest. "He's not even here," went the conversation. "Bandura." "Where the hell is he?" "At the hospital in El Paso." "What? Why weren't we informed? What's wrong with him?" Go Team Bandura! Go Team Banzai! Go Team Banzai! ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
The result is not quite right. You forgot the trailing g, so vi changed only the very first occurrence on each line, making the "go team" exhortation rather confusing.
To try again, type :1,$ s/Banzai/Bandura/g and press Return. The screen changes as desired:
Excerpt from "Buckaroo Bandura" by Duke MacRauch I found myself stealing a peek at my own watch and overhead General Catbird's aide give him the latest. "He's not even here," went the conversation. "Bandura." "Where the hell is he?" "At the hospital in El Paso." "What? Why weren't we informed? What's wrong with him?" Go Team Bandura! Go Team Bandura! Go Team Bandura! ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ 7 substitutions
Notice that vi also indicates the total number of substitutions in this case.
Press u to undo the last change.
Search and replace is one area where a windowing system, like that on a Macintosh or a PC running Windows, comes in handy. A windowing system offers different boxes for the old and new patterns, and shows each change and a dialog box asking,
"Should I change this one?" Alas, this is UNIX and it's still designed to run on ASCII terminals.
As you have worked through the various examples, you might have tried pressing the arrow keys on your keyboard or perhaps the Ins or Del keys. Odds are likely that the keys not only didn't work, but instead caused all sorts of weird things to happen!
The good news is that vi has a facility that enables you to map any key to a specific action. If these key mappings are saved in a file called .exrc in your home directory, the mappings will be understood by vi automatically each time you use the
program. The format for using the map command is :map key command-sequence. (In a nutshell, mapping is a way of associating an action with another action or result. For example, by plugging your computer into the right wall socket, you could
map the action of flipping the light switch on the wall with the result of having your computer turn on.)
You can also save other things in your .exrc file, including the :set number option if you're a nut about seeing line numbers. More interestingly, vi can be taught abbreviations, so that each time you press the abbreviation, vi expands it. The format
for defining abbreviations is :abbreviate abbreviation expanded-value. Finally, any line that begins with a double quote is considered a comment and is ignored.
It's finally time to leave the buckaroo.confused file, and restart vi, this time with the .exrc file in your home directory:
% cd % vi .exrc _ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ".exrc" [New file]
Before you actually add any information to this new file, define a few abbreviations to make life a bit easier. To do this, press :, which moves the cursor to the bottom of the screen. Then define tyu as a simple abbreviation for the lengthy phrase
Teach Yourself UNIX in a Few Minutes:
~ ~ ~ :abbreviate tyu Teach Yourself UNIX in a Few Minutes_
Pressing Return moves the cursor back to the top.
Now try the abbreviation. Recall that in the .exrc, lines beginning with a double quote are comments and are ignored when vi starts up. Press i to enter insert mode, and then type " Sample .exrc file as shown in tyu. The screen looks like this:
" Sample .exrc file as shown in tyu_ ~ ~
As soon as you press Return or enter a space or punctuation character, the abbreviation is expanded. In this case, move to the next line by pressing Return:
" Sample .exrc file as shown in Teach Yourself UNIX in a Few Minutes _ ~ ~
Press Esc to leave the insert mode.
This feature can also be used to correct common typos you make. Many people have a bad habit of typing "teh" instead of "the." Because vi is smart about abbreviation expansion, you can abbreviate "the" as "teh"
and not get into trouble:
~ ~ :ab teh the_
Press Return. Now whenever you make that typo, the editor will fix it. To demonstrate this, add a second comment to this file. Adding a comment is easy because you're still at the beginning of the second line. When you press i and type " (subtly
different from the example in teh, you get the following result:
" Sample .exrc file as shown in Teach Yourself UNIX in a Few Minutes " (subtly different from the example in the_ ~ ~
If you enter another character instead of pressing the spacebar, vi is smart enough not to expand the abbreviation. Try it yourself. After pressing the h key again, you'll see this:
" Sample .exrc file as shown in Teach Yourself UNIX in a Few Minutes " (subtly different from the example in tehh_ ~ ~
Because you're still in insert mode, however, you can backspace and replace the spare h with a space, which instantly fixes the spelling. Finally, type book) and press Esc to return to command mode.
There's one more nifty abbreviation trick. Type :ab by itself and press Return. vi shows you a list of the abbreviations currently in effect:
~ ~ :ab tyu tyu Teach Yourself UNIX in a Few Minutes teh teh the [Hit any key to continue] _
Okay, now you can move on to key mapping.
Key mapping is as easy as defining abbreviations, except you must remember one thing: any control character entered must be prefaced with a ^v so that vi doesn't interpret it immediately. The Esc key is included in this list, too.
To map the Clear key to the D function, which, as you recall, deletes text through the end of the current line, type :map, followed by a single space:
~ ~ :map
Now you need to type the ^v; otherwise, when you press the Clear key, it will send an Escape sequence that will confuse vi to no end. Press ^v:
~ ~ :map ^
The cursor is floating over the caret, which indicates the next character typed should be a control character. Instead of pressing any specific character, however, simply press the Clear key. The result is that it sends the Escape sequence, and vi
captures it without a problem:
~ ~ :map ^[OP_
Now type another space, because the key part of the key mapping has been defined. Then type the command to which vi should map the Clear key:
~ ~ :map ^[OP D_
Press Return, and it's done! To test the key mapping, move back to the phrase Few Minutes in the first line:
" Sample .exrc file as shown in Teach Yourself UNIX in a Few Minutes " (subtly different from the example in the book) ~ ~
To clear this line, you need only press Clear.
To save this as a permanent key mapping in this .exrc file, duplicate each keystroke, but this time do it in insert mode instead of at the bottom of the screen. The result is a file that looks like this:
" Sample .exrc file as shown in Teach Yourself UNIX in a " (subtly different from the example in the book) :map ^[OP D_ ~ ~
Mapping the arrow keys is done the same way, and typing :ab and then pressing Return shows all abbreviations. Typing :map and then Return demonstrates that you already have your arrow keys mapped to the vi motion keys:
~ ~ :map up ^[[A k down ^[[B j left ^[[D h right ^[[C l ^[OP ^[OP D [Hit any key to continue] _
You can see that sometimes the system can be smart about defining specific keys by name rather than by value, but the end result is the same. You can now use the arrow keys and Clear key, and vi knows what they mean.
Here's a final demonstration of what you can do with keyboard mapping. You'll often encounter a simple, tedious activity you must do over and over. An example might be surrounding a specific word with quotes to meet a style guideline. This sounds more
painful than it need be, because a simple key mapping can automate the entire process of quoting the current word.
You know that ^a isn't used by vi, so you can map that to the new quote-a-single-word command, making sure that you use ^v before each control character or Esc. Type the characters :map ^v^a i":
~ ~ :map ^A i"_
Press ^v and then the Esc key. To insert a double quote, you need to have vi go into insert mode (the i), type the quote, and receive an Esc to leave insert mode. The e command moves to the end of the current word, so type that, followed by the commands
needed to append the second double quote. The final map now looks like this:
~ ~ :map ^A i"^[ea"^[_
Press Return and it's done. Now move to the beginning of a word and try the new key mapping for ^a.
There are a variety of customizations you can use with the vi editor, including teaching it about special keys on your keyboard and defining task-specific keys to save time. You can use it to abbreviate commonly used words or phrases to save time or
avoid typographical errors. Be cautious when working with the .exrc file, however, because if you enter information that isn't valid, it can be a bit confusing to fix it. Always try the command directly before using it in a special key mapping, and you'll
stay out of trouble.
You've learned quite a variety of different commands for moving about in files, but there are two more vi movement commands for you to try. So far, movement has been based on screen motion, but vi hasn't particularly known much about the information in
the file itself: press k and you move up a line, regardless of what kind of file you're viewing.
The vi editor is smarter than that, however. It has some movement commands that are defined by the text you're currently editing. Each of these is simply a punctuation character on your keyboard, but each is quite helpful. The first is ), which moves
the cursor forward to the beginning of the next sentence in the file. Use the opposite, (, and you can move to the beginning of the current sentence in the file. Also worth experimenting with is }, which moves forward a paragraph in the file, and {, which
moves backwards a paragraph.
To try this out, create a new file. Start vi and type the following text:
% cat dickens.note
A Tale of Two Cities
Preface
When I was acting, with my children and friends, in Mr Wilkie Collins's
drama of The Frozen Deep, I first conceived the main idea of this
story. A strong desire was upon me then, to
embody it in my own person;
and I traced out in my fancy, the state of mind of which it would
necessitate the presentation
to an observant spectator, with particular
care and interest.
As the idea became familiar to me, it gradually shaped itself into its
present form. Throughout its execution, it has had complete possession
of me; I have so far verified what
is done and suffered in these pages,
as that I have certainly done and suffered it all myself.
Whenever any reference (however slight) is made here to the condition
of the French people before or during the Revolution, it is truly made,
on the faith of the most trustworthy
witnesses. It has been one of my hopes to add
something to the popular and picturesque means of
understanding that terrible time, though no one can hope
to add anything to the philosophy of Mr Carlyle's wonderful book.
Tavistock House
November 1859
When you start vi on this file, here's what your initial screen looks like:
A Tale of Two Cities
Preface
When I was acting, with my children and friends, in Mr Wilkie Collins's
drama of The Frozen Deep, I first conceived the main idea of this
story. A strong desire was upon me then, to
embody it in my own person;
and I traced out in my fancy, the state of mind of which it would
necessitate the presentation
to an observant spectator, with particular
care and interest.
As the idea became familiar to me, it gradually shaped itself into its
present form. Throughout its execution, it has had complete possession
of me; I have so far verified what
is done and suffered in these pages,
as that I have certainly done and suffered it all myself.
Whenever any reference (however slight) is made here to the condition
of the French people before or during the Revolution, it is truly made,
on the faith of the most trustworthy
witnesses. It has been one of my hopes to add
something to the popular and picturesque means of
"dickens.note" 28 lines, 1122 characters
Move to the beginning of the first paragraph of text by typing /When and pressing Return. Now the screen looks like this:
A Tale of Two Cities
Preface
When I was acting, with my children and friends, in Mr Wilkie Collins's
drama of The Frozen Deep, I first conceived the main idea of this
story. A strong desire was upon me then, to
embody it in my own person;
Press ) once. The cursor moves to the beginning of the next sentence:
When I was acting, with my children and friends, in Mr Wilkie Collins's drama of The Frozen Deep, I first conceived the main idea of this story. A strong desire was upon me then, to embody it in my own person; and I traced out in my fancy, the state of mind of which it would necessitate the presentation
Try the ( to move back a sentence. You end up back on the "W" in "When" at the beginning of the sentence. Repeatedly pressing ( and ) should let you fly back and forth through the file, sentence by sentence. Notice what occurs when
you're at the top few lines of the title.
You can move back to the opening word of the first paragraph by pressing n to repeat the last search pattern. The screen now looks like this:
A Tale of Two Cities
Preface
When I was acting, with my children and friends, in Mr Wilkie Collins's
drama of The Frozen Deep, I first conceived the main idea of this
story. A strong desire was upon me then, to
embody it in my own person;
and I traced out in my fancy, the state of mind of which it would
necessitate the presentation
to an observant spectator, with particular
care and interest.
As the idea became familiar to me, it gradually shaped itself into its
present form. Throughout its execution, it has had complete possession
of me; I have so far verified what
is done and suffered in these pages,
as that I have certainly done and suffered it all myself.
Whenever any reference (however slight) is made here to the condition
of the French people before or during the Revolution, it is truly made,
on the faith of the most trustworthy
witnesses. It has been one of my hopes to add
something to the popular and picturesque means of
"dickens.note" 28 lines, 1122 characters
To move to the next paragraph, press } once:
A Tale of Two Cities
Preface
When I was acting, with my children and friends, in Mr Wilkie Collins's
drama of The Frozen Deep, I first conceived the main idea of this
story. A strong desire was upon me then, to
embody it in my own person;
and I traced out in my fancy, the state of mind of which it would
necessitate the presentation
to an observant spectator, with particular
care and interest.
As the idea became familiar to me, it gradually shaped itself into its
present form. Throughout its execution, it has had complete possession
of me; I have so far verified what
is done and suffered in these pages,
as that I have certainly done and suffered it all myself.
Whenever any reference (however slight) is made here to the condition
of the French people before or during the Revolution, it is truly made,
on the faith of the most trustworthy
witnesses. It has been one of my hopes to add
something to the popular and picturesque means of
"dickens.note" 28 lines, 1122 characters
Press the { key and you move right back to the beginning of the previous paragraph. In fact, you can easily fly back and forth in the file by using sequences of } (or a numeric repeat prefix like 2} to get there faster).
These two motion commands are helpful when you're working with stories, articles, or letters. Anytime you're working with words rather than commands (as in the .exrc file), these commands are worth remembering.
By the way, try d) to delete a sentence, or c} to change an entire paragraph. Remember that you can always undo the changes with u if you haven't done anything else between the two events.
This final section on vi introduces you to one of the most powerful, and least known, commands in the editor: the ! Escape-to-UNIX command. When prefaced with a colon (:!, for example), it enables you to run UNIX commands without leaving the editor.
More importantly, the ! command itself, just like d and c, accepts address specifications and feeds that portion of text to the command, and then replaces that portion with the results of having run that command on the text.
You should still be in the dickens.intro file. Start by double-checking what files you have in your home directory. To do this, type :!, which moves the cursor to the bottom line:
of the French people before or during the Revolution, it is truly made, on the faith of the most trustworthy witnesses. It has been one of my hopes to add something to the popular and picturesque means of :!_
Type ls -CF and press Return, as if you were at the % prompt in the command line:
of the French people before or during the Revolution, it is truly made, on the faith of the most trustworthy witnesses. It has been one of my hopes to add something to the popular and picturesque means of :!ls -CF Archives/ big.output dickens.note src/ InfoWorld/ bigfiles keylime.pie temp/ Mail/ bin/ newfile tetme News/ buckaroo owl.c OWL/ buckaroo.confused sample awkscript demo sample2 [Hit any key to continue] _
Press Return and you're back in the editor. You have quickly checked what files you have in your home directory. (Your fileage may vary.)
Now for some real fun. Move back to the beginning of the first paragraph and add the text "Chuck, here are my current files:" to it. Press Return twice before using the Esc key to return to command mode:
A Tale of Two Cities
Preface
Chuck, here are my current files:
_
When I was acting, with my children and friends, in Mr Wilkie Collins's
drama of The Frozen Deep, I first conceived the main idea of this
story. A strong desire was upon me then, to
Notice that the cursor was moved up a line. You're now on a blank line, and the line following is also blank.
To feed the current line to the UNIX system and replace it with the output of the command, vi offers an easy shortcut: !!. As soon as you type the second ! (or, more precisely, once vi figures out the desired range specified for this command), the
cursor moves to the bottom of the screen and prompts with a single ! character:
of the French people before or during the Revolution, it is truly made, on the faith of the most trustworthy witnesses. It has been one of my hopes to add something to the popular and picturesque means of !_
To list all the files in your directory, again type ls -CF and press Return. After a second, vi adds the output of that command to the file:
A Tale of Two Cities
Preface
Chuck, here are my current files:
Archives/ bigfiles newfile
InfoWorld/ bin/ owl.c
Mail/ buckaroo sample
News/ buckaroo.confused sample2
OWL/ demo src/
awkscript dickens.note temp/
big.output keylime.pie tetme
When I was acting, with my children and friends, in Mr Wilkie Collins's
drama of The Frozen Deep, I first conceived the main idea of this
story. A strong desire was upon me then, to
embody it in my own person;
and I traced out in my fancy, the state of mind of which it would
necessitate the presentation
to an observant spectator, with particular
care and interest.
As the idea became familiar to me, it gradually shaped itself into its
present form. Throughout its execution, it has had complete possession
6 more lines
Notice that this time that the status on the bottom indicates how many lines were added to the file.
Press u to undo this change. Notice that the vi status indicator on the bottom line says there are now six fewer lines.
Move back to the "W" in "When." You are now ready to learn one of the most useful commands in vi. This command gives you the ability to hand a paragraph of text to an arbitrary UNIX command.
This time, use a sed command, sed 's/^/> /', which prefaces each line with >. Ready? This is where the } command comes in handy, too. To accomplish this trick, type !}, moving the cursor to the bottom of the screen. Then type the sed command as
you saw earlier: sed 's/^/> /'. Pressing Return feeds the lines to sed. The sed command makes the change indicated and replaces those lines with the output of the sed command. Voilà! The screen now looks like this:
A Tale of Two Cities
Preface
Chuck, here are my current files:
> When I was acting, with my children and friends, in Mr Wilkie Collins's
> drama of The Frozen Deep, I first conceived the main idea of this
> story. A strong desire was upon me then, to
> embody it in my own person;
> and I traced out in my fancy, the state of mind of which it would
> necessitate the presentation
> to an observant spectator, with particular
> care and interest.
As the idea became familiar to me, it gradually shaped itself into its
present form. Throughout its execution, it has had complete possession
of me; I have so far verified what
is done and suffered in these pages,
as that I have certainly done and suffered it all myself.
Whenever any reference (however slight) is made here to the condition
of the French people before or during the Revolution, it is truly made,
!sed 's/^/> /'
Here are a few more examples of ways to interact with UNIX while within vi. First, you don't really want the prefix to each line, so choose u to undo the change.
You want the system to actually tighten up the lines, ensuring that a reasonable number of words occur on each line without any lines being too long. On the majority of systems, there is a command called either fmt or adjust to accomplish this. To
figure out which works on your system, simply use the :! command and feed a word or two to the fmt command to see what happens:
Whenever any reference (however slight) is made here to the condition of the French people before or during the Revolution, it is truly made, :!echo hi | fmt [No write since last change] hi [Hit any key to continue] _
In this case, fmt worked as expected, so you can be sure that the command exists on your system. If the response was command unknown, adjust is a likely synonym. If neither exist, complain to your vendor!
Armed with this new command, you can try another variant of !}, this time by feeding the entire paragraph to the fmt command. You're still at the beginning of the word "When" in the text. When you type the command !}fmt, the paragraph is
cleaned up, and the screen changes to this:
A Tale of Two Cities
Preface
Chuck, here are my current files:
When I was acting, with my children and friends, in Mr Wilkie Collins's
drama of The Frozen Deep, I first conceived the main idea of this
story. A strong desire was upon me then, to embody it in my own
person; and I traced out in my fancy, the state of mind of which it
would necessitate the presentation to an observant spectator, with
particular care and interest.
As the idea became familiar to me, it gradually shaped itself into its
present form. Throughout its execution, it has had complete possession
of me; I have so far verified what
is done and suffered in these pages,
as that I have certainly done and suffered it all myself.
Whenever any reference (however slight) is made here to the condition
of the French people before or during the Revolution, it is truly made,
on the faith of the most trustworthy
witnesses. It has been one of my hopes to add
2 fewer lines
Again, vi tells you that the number of lines in the file have changed as a result of the command. In this situation, tightening up the paragraph actually reduced it by two display lines, too.
This command is so helpful that you may want to have it bound to a specific key with the keymap command. A typical way to do this in an .exrc might be this:
:map ^P !}fmt^M
The ^M is what vi uses to record an Return keypress. (Remember that you need to use ^v beforehand.) With this defined in your .exrc, you can press ^p to format the current paragraph.
The awk command, discussed in Chapter 15, "Awk, Awk," can easily be used to extract specific fields of information. This can be tremendously helpful in vi. Rather than continuing with the dickens.intro file, however, quit vi and create a new
file containing some output from the ls command:
% ls -CF Archives/ big.output dickens.note src/ InfoWorld/ bigfiles keylime.pie temp/ Mail/ bin/ newfile tetme News/ buckaroo owl.c OWL/ buckaroo.confused sample awkscript demo sample2 % ls -l a* b* > listing
Now you can use vi listing to start the file with the output of the ls command:
-rw-rw 1 taylor 126 Dec 3 16:34 awkscript -rw-rw 1 taylor 1659 Dec 3 23:26 big.output -rw-rw 1 taylor 165 Dec 3 16:42 bigfiles -rw-rw 1 taylor 270 Dec 4 15:09 buckaroo -rw-rw 1 taylor 458 Dec 4 23:22 buckaroo.confused ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ "listing" 5 lines, 282 characters
It would be nice to use this as the basis for creating a shell script, which is just a series of commands that you might type to the shell directly, all kept neatly in a single file. A shell script can show you both the first and last few lines of each
file, with the middle chopped out.
The commands you want to have occur for each file entry are these:
echo ==== filename ==== head -5 filename; echo ...size bytes...; tail -5 filename
Do this with a combination of the ! command in vi and the awk program with the awk command:
awk '{ print "echo ==== "$8" ===="; print "head "$8"; echo
..."$4" bytes...; tail "$8}'
With the cursor on the very top line of this file, you can now press !G to pipe the entire file through the command. The cursor drops to the bottom of the screen. Type in the awk script shown previously and press Return. The result is this:
echo ==== awkscript ====
head -5 awkscript; echo ...126 bytes...; tail -5 awkscript
echo ==== big.output ====
head -5 big.output; echo ...1659 bytes...; tail -5 big.output
echo ==== bigfiles ====
head -5 bigfiles; echo ...165 bytes...; tail -5 bigfiles
echo ==== buckaroo ====
head -5 buckaroo; echo ...270 bytes...; tail -5 buckaroo
echo ==== buckaroo.confused ====
head -5 buckaroo.confused; echo ...458 bytes...; tail -5 buckaroo.confused~
~
~
~
~
~
~
~
~
~
~
~
~
!awk '{ print "echo ==== "$8" ===="; print "head "$8"; echo
..."$4" bytes...; tail "$8}'
If you now quit vi and ask sh to interpret the contents, here's what happens:
% chmod +x listing
% sh listing
==== awkscript ====
{
count[length($1)]++
}
END {
for (i=1; i < 9; i++)
...126 bytes...
}
END {
for (i=1; i < 9; i++)
print "There are " counti " accounts with " i " letter names."
}
==== big.output ====
leungtc ttyrV Dec 1 18:27 (magenta)
tuyinhwa ttyrX Dec 3 22:38 (expert)
hollenst ttyrZ Dec 3 22:14 (dov)
brandt ttyrb Nov 28 23:03 (age)
holmes ttyrj Dec 3 21:59 (age)
...1659 bytes...
buckeye ttyss Dec 3 23:20 (mac2)
mtaylor ttyst Dec 3 23:22 (dov)
look ttysu Dec 3 23:12 (age)
janitor ttysw Dec 3 18:29 (age)
ajones ttysx Dec 3 23:23 (rassilon)
==== bigfiles ====
12556 keylime.pie
8729 owl.c
1024 Mail/
582 tetme
512 temp/
...165 bytes...
512 Archives/
207 sample2
199 sample
126 awkscript
==== buckaroo ====
I found myself stealing a peek at my own watch and overhead
General Catbird's
aide give him the latest.
"He's not even here," went the conversation.
"Banzai."
"Where the hell is he?"
...270 bytes...
"Banzai."
"Where the hell is he?"
"At the hospital in El Paso."
"What? Why weren't we informed? What's wrong with him?"
==== buckaroo.confused ====
Excerpt from "Buckaroo Bandura" by Duke MacRauch
I found myself stealing a peek at my own watch and overhead
General Catbird's
aide give him the latest.
"He's not even here," went the conversation.
"Bandura."
...458 bytes...
"At the hospital in El Paso."
"What? Why weren't we informed? What's wrong with him?"
Go Team Bandura! Go Team Bandura! Go Team Bandura!
%
Clearly the ! command opens up vi to work with the rest of the UNIX system. There's almost nothing that you can't do within the editor, whether it's add or remove prefixes, clean up text, or even show what happens when you try to run a command or
reformat a passage within the current file. Remember, you can run spell without leaving vi, too. Be careful, though, because spell will replace the entire contents of your file with the list of words it doesn't know. Fortunately, u can solve that problem.
A summary of the commands you have learned in this section is shown in Table 7.3.
Command |
Meaning |
|
!! |
Replace current line with output of UNIX command. |
|
!} |
Replace current paragraph with the results of piping it through the specified UNIX program or programs. |
|
( |
Move backward one sentence. |
|
) |
Move forward one sentence. |
|
C |
Change text through the end of line. |
|
c |
Change text in the specified rangecw c |