You've already learned quite a few commands, but you've barely scratched the surface of the powerful vi command!
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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 guide) 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 guide) ~ ~
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 guide) :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 guide.
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 changes the following word, whereas c} changes the next paragraph. |
|
e |
Move to the end of the current word. |
|
^g |
Show current line number and other information about the file. |
|
R |
Replace text until Esc. |
|
r |
Replace the current character with the next pressed. |
|
^v |
Prevent vi from interpreting the next character. |
|
{ |
Move backward one paragraph. |
|
} |
Move forward one paragraph. |
|
:! |
Invoke specified UNIX command. |
|
:ab a bcd |
Define abbreviation a for phrase bcd. |
|
:ab |
Show current abbreviations, if any. |
|
:map a bcd |
Map key a to the vi commands bcd. |
|
:map |
Show current key mappings, if any. |
|
:s/old/new/ |
Substitute new for old on the current line. |
|
:s/old/new/g |
Substitute new for all occurrences of old on the current line. |
|
:1,$s/old/new/g |
Substitute new for all occurrences of old. |
|
:set nonumber |
Turn off line numbering. |
|
:set number |
Turn on line numbering. |
Clearly, vi is a very complex and sophisticated tool, allowing you to not only modify your text files but also customize the editor for your keyboard. Just as important, you can access all the power of UNIX while within vi.
With this section and the last, you now know more about vi than the vast majority of people using UNIX today. There's a second popular editor, however; one that is modeless and that offers its own interesting possibilities for working with files and the
UNIX system. It's called EMACS, and if you have it on your system, it's definitely worth a look.
The only screen-oriented editor that's guaranteed to be included with the UNIX system is vi, but that doesn't mean that it's the only good editor available. An alternative editor that has become quite popular in the last decade (remember that UNIX is
almost twenty-five years old) is called EMACS. This section teaches you the fundamentals of this powerful editing environment.
Remember that EMACS is modeless, so be prepared for an editor that is quite unlike vi. Because it's modeless, there's no insert or command mode. The result is that you have ample opportunity to use the Ctrl key.
Starting EMACS is as simple as starting any other UNIX program. Simply type the name of the program, followed by any file or files you'd like to work with. The puzzle with EMACS is figuring out what it's actually called on your system, if you even have
it.
Once in EMACS, it's important to take a look at your computer keyboard. EMACS requires you to use not just the Ctrl key, but another key known as the Meta key, a sort of alternative Ctrl key. If you have a key labelled Meta or Alt on your keyboard,
that's the one. If, like me, you don't, press Esc every time a Meta key is indicated.
Because there are both Ctrl and Meta keys in EMACS, the notation for indicating commands is slightly different. Throughout this chapter, a control key sequence has been shown either as Ctrl+F or ^f. EMACS people write this differently to allow for the
difference between the Ctrl and Meta keys. In EMACS notation, ^f is shown as C-f, where C- always means Ctrl. Similarly, M-x is the Meta key plus x. If you don't have a Meta key, the sequence is Esc, followed by x. Finally, some arcane commands involve
both the Ctrl and Meta keys being pressed simultaneously with the other key involved. The notation is C-M-x. This indicates that you need to either press and hold down both the Ctrl and Meta keys while pressing x, or, if you don't have a Meta (or Alt) key,
press Esc followed by C-x.
With this notation in mind, leave EMACS by pressing C-x C-c (Ctrl+X, followed by Ctrl+C).
First, see if your system has EMACS available. The easiest way to find out is to type emacs at the command line and see what happens.
% emacs emacs: Command not found. %
This is a good indication that EMACS isn't available. If your command worked and you now are in the EMACS editor, move down to step 2.
A popular version of EMACS, called GNU EMACS, comes from the Free Software Foundation. To see if you have this version, type gnuemacs or gnumacs at the command line.
If this fails to work, you can try one more command before you accept that EMACS isn't part of your installation of UNIX. Online documentation for UNIX is accessible through the man command. The actual database of documents also includes a primitive but
helpful keyword search capability, accessible by specifying the -k option (for keyword searches) at the command line. To find out if you have EMACS, enter the following:
% man -k emacs gnuemacs (1l) - GNU project Emacs %
This indicates that GNU EMACS is on the system and can be started by entering gnuemacs at the command line.
Rather than start with a blank screen, quit the program (C-x C-c) and restart EMACS with one of the earlier test files, dickens.note:
% gnuemacs 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
Emacs: dickens.note (Fundamental)Top-
As you can see, it's quite different from the display shown when vi starts up. The status line at the bottom of the display offers useful information as you edit the file at different points. It also displays the name of the file at all times, a feature
that can be surprisingly helpful. EMACS can work with different kinds of files. Here you see by the word "Fundamental" in the status line that EMACS is prepared for a regular text file. If you're programming, EMACS can offer special features
customized for your particular language.
Quit EMACS by using the C-x C-c sequence, but let a few seconds pass after you press C-x to see what happens. When you press C-x, the bottom of the screen suddenly changes to this:
on the faith of the most trustworthy witnesses. It has been one of my hopes to add Emacs: dickens.note (Fundamental)Top C-x-
Confusingly, the cursor remains at the top of the file, but EMACS reminds you that you've pressed C-x and that you need to enter a second command once you've decided what to do. Press C-c and immediately exit EMACS.
Already you can see there are some dramatic differences between EMACS and vi. If you're comfortable with multiple key sequences like C-x C-c to quit, you're going to enjoy learning EMACS. If not, stick with it anyway. Even if you never use EMACS, it's
good to know a little bit about it.
Files are composed of characters, words, lines, sentences, and paragraphs, and EMACS has commands to help you move around in them. Most systems have the arrow keys enabled, which means you won't need some of the key sequences, but it's best to know them
all anyway.
The most basic motions are C-f and C-b, which are used to move the cursor forward and backward one character, respectively. Switch those to the Meta command equivalents and the cursor will move word by word: M-f moves the cursor forward a word and M-b
moves it back a word. Pressing C-n moves the cursor to the next line, C-p moves it to the previous line, C-a moves it to the beginning of the line, and C-e moves it to the end of the line. (The vi equivalents for these are l, h, w, and b for moving forward
and backward a character or word; j and k for moving up or down a line; and 0 or $ to move to the beginning or end of the current line. Which makes more sense to you?)
To move forward a sentence you can use M-e, which actually moves the cursor to the end of the sentence. Pressing M-a moves it to the beginning of the sentence. Notice the parallels between Ctrl and Meta commands: C-a moves the cursor to the beginning of
the line, and M-a moves it to the beginning of the sentence.
Scrolling within the document is accomplished by using C-v to move forward a screen and M-v to move back a screen. To move forward a page (usually 60 lines of text; this is based on a printed page of information), you can use either C-x ] or C-x [ for
forward or backward motion, respectively.
Finally, to move to the very top of the file, use M-<, and to move to the bottom, use M->.
Go back into EMACS and locate the cursor. It should be at the very top of the screen:
_ 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 posession
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
Emacs: dickens.note (Fundamental)Top-
Move down four lines by using C-n four times. You should now be sitting on the "d" in "drama":
Preface When I was acting, with my children and friends, in Mr Wilkie Collins's [d]rama 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
Next, move to the end of this sentence by using the M-e command (just like vi, EMACS expects two spaces to separate sentences):
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
Now type in the following text: I fought the impulse to write this novel vociferously, but, dear reader, I felt the injustice of the situation too strongly in my breast to deny. Don't press Return or Esc when you're done. The screen should now look
similar to this:
drama of The Frozen Deep, I first conceived the main idea of this story. I fought the impulse to write this novel vociferously, but, dear reader,\ I felt the injustice of the situation too strongly in my breast to deny_ A strong des\ ire 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
You can see that EMACS wrapped the line when it became too long (between the words "felt" and "the"), and because the lines are still too long to display, a few of them end with a backslash. The backslash isn't actually a part of the
file; with it, EMACS is telling you that those lines are longer than you might expect.
Now try to move back a few letters by pressing Backspace.
Uh-oh! If your system is like mine, the Backspace key doesn't move the cursor back a letter at all. Instead it starts the EMACS help system, where you're suddenly confronted with a screen that looks like this:
You have typed C-h, the help character. Type a Help option:
A command-apropos. Give a substring, and see a list of commands
(functions interactively callable) that contain
that substring. See also the apropos command.
B dEscribe-bindings. Display table of all key bindings.
C dEscribe-key-briefly. Type a command key sequence;
it prints the function name that sequence runs.
F dEscribe-function. Type a function name and get documentation of it.
I info. The info documentation reader.
K dEscribe-key. Type a command key sequence;
it displays the full documentation.
L view-lossage. Shows last 100 characters you typed.
M dEscribe-mode. Print documentation of current major mode,
which dEscribes the commands peculiar to it.
N view-emacs-news. Shows emacs news file.
S dEscribe-syntax. Display contents of syntax table, plus explanations
T help-with-tutorial. Select the Emacs learn-by-doing tutorial.
V dEscribe-variable. Type name of a variable;
it displays the variable's documentation and value.
W where-is. Type command name; it prints which keystrokes
invoke that command.
**-Emacs: *Help* (Fundamental)Top-
A B C F I K L M N S T V W C-c C-d C-n C-w or Space to scroll: _
To escape the help screen, press Esc. Your screen should be restored. Notice that the filename has been changed and is now shown as *Help* instead of the actual file. The status line also shows what file you're viewing, but you aren't always viewing the
file you want to work with.
The correct keys to move the cursor back a few characters are C-b. Use them to back up. Then use C-f to move forward again to the original cursor location.
Check that the last few lines of the file haven't changed by using the EMACS move-to-end-of-file command M->. (Think of file redirection to remember the file motion commands). Now the screen looks like this:
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 guide. Tavistock House November 1859 _ **-Emacs: dickens.note (Fundamental)Bot-
Changing the words of Charles Dickens was fun, so save these changes and quit. If you try to quit the program with C-x C-c, EMACS reminds you that there are unsaved changes:
**-Emacs: dickens.note (Fundamental)Bot- Save file /users/taylor/dickens.note? (y or n) _
Pressing y saves the changes, and n quits without saving the changes. If you instead decide to return to the edit session, Esc cancels the action entirely. Pressing n reminds you a second time that the changes are going to be lost if you don't save
them.
**-Emacs: dickens.note (Fundamental)Bot- Modified buffers exist; exit anyway? (yes or no) _
This time type yes and, finally, you're back on the command line.
Entering text in EMACS is incredibly easy. It's as if the editor is always in insert mode. The price that you pay for this, however, is that just about anything else you do requires Ctrl or Meta sequences: even the Backspace key did something other than
what you wanted. (You could fix the problem with key mapping so that pressing that key results in a C-b command, but then you couldn't get to the help information.)
The motion commands are summarized in Table 7.4.
Command |
Meaning |
|
M-> |
Move to end of file. |
|
M-< |
Move to beginning of file. |
|
C-v |
Move forward a screen. |
|
M-v |
Move backward a screen. |
|
C-x ] |
Move forward a page. |
|
C-x [ |
Move backward a page. |
|
C-n |
Move to the next line. |
|
C-p |
Move to the previous line. |
|
C-a |
Move to the beginning of the line. |
|
C-e |
Move to the end of the line. |
|
M-e |
Move to the end of the sentence. |
|
M-a |
Move to the beginning of the sentence. |
|
C-f |
Move forward a character. |
|
C-b |
Move backward a character. |
|
M-f |
Move forward a word. |
|
M-b |
Move backward a word. |
Inserting text into an EMACS buffer is quite simple, and once you get the hang of it, moving about in the file isn't too bad either. How about deleting text? The series of Ctrl and Meta commands that allow you to insert text are a precursor to all
commands in EMACS, and it should come as no surprise that C-d deletes the current character, M-d deletes the next word, M-k deletes the rest of the current sentence, and C-k deletes the rest of the current line. If you have a key on your keyboard labeled
DEL, RUBOUT, or Delete, you're in luck, because DEL deletes the previous character, M-DEL deletes the previous word, and C-x DEL deletes the previous sentence.
I have a Delete key, but it's tied to the Backspace function on my system. Every time I press it, it actually sends a C-h sequence to the system, not the DEL sequence. The result is that I cannot use any of these backwards deletion commands.
Restart EMACS with the dickens.note file and move the cursor to the middle of the fifth line (remember, C-n moves to the next line, and C-f moves forward a character). It should look like this:
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 [w]as 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
Notice that my cursor is on the "w" in "was" on the fifth line here.
Press C-d C-d C-d to remove the word "was." Now simply type came to revise the sentence slightly. The screen should now look like this:
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 came_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
Now press DEL once to remove the last letter of the new word and press e to reinsert it. Instead of backing up a character at a time, instead use M-DEL to delete the word just added. The word is deleted, but the spaces on either side of the word are
retained.
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 _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
Try another word to see if you can get this sentence to sound better. Type crept to see how it reads.
On the other hand, it's probably not good to revise classic stories like A Tale of Two Cities, so the best move is to delete this entire sentence. If you press C-x DEL, will it do the right thing? Remember, C-x DEL deletes the previous sentence. Press
C-x DEL and the results are helpful, if not completely what you want to accomplish:
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. _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
That's okay. Now you can delete the second part of the sentence by using the M-k command. Now the screen looks like what you want:
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. _ As the idea became familiar to me, it gradually shaped itself into its present form. Throughout its execution, it has had complete posession of me; I have so far verified what
Here's a great feature of EMACS! You just realized that deleting sentences is just as wildly inappropriate as changing words, so you want to undo the last two changes. If you were using vi you'd be stuck, because vi remembers only the last change; but
EMACS has that beat. With EMACS, you can back up as many changes as you'd like, usually until you restore the original file. To step backwards, use C-x u.
The first time you press C-x u, the screen changes to this:
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. _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 posession
The second time you press it, the screen goes even further back in your revision history:
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 crept_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 posession
Finally, pressing C-x u three more times causes the original text to be restored:
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 [c]ame 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 posession
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
**-Emacs: dickens.note (Fundamental)Top-
Undo!
Regrettably, if you don't have a DELETE key, some of the deletion commands will be unavailable to you. Generally, though, EMACS has as many ways to delete text as vi has, if not more. The best feature is that, unlike vi, EMACS remembers changes from the
beginning of your editing session. You can always back up as far as you want by using the C-x u undo request.
The delete keys are summarized in Table 7.5.
Command |
Meaning |
|
DEL |
Delete the previous character. |
|
C-d |
Delete the current character. |
|
M-DEL |
Delete the previous word. |
|
M-d |
Delete the next word. |
|
C-x DEL |
Delete the previous sentence. |
|
M-k |
Delete the rest of the current sentence. |
|
C-k |
Delete the rest of the current line. |
|
C-x u |
Undo the last edit change. |
Because EMACS reserves the last line of the screen for its own system prompts, searching and replacing is easier than in vi. Moreover, the system prompts for the fields and asks, for each occurrence, whether to change it or not. On the other hand, this
command isn't a simple key press or two, but rather it is an example of a named EMACS command.
Searching forward for a pattern is done by pressing C-s and searching backwards with C-r (the mnemonics are search forward and reverse search). To leave the search once you've found what you want, press Esc. To cancel the search, returning to your
starting point, use C-g.
Query and replace is really a whole new feature within EMACS. To start a query and replace, use M-x query-replace. EMACS will prompt for what to do next. Once a match is shown, you can type a variety of different commands to affect what happens: y makes
the change; n means to leave it as is, but move to the next match; Esc or q quits replace mode; and ! automatically replaces all further occurrences of the pattern without further prompting.
You're still looking at the dickens.note file, and you have moved the cursor to the top-left corner by using M-<. Somewhere in the file is the word "Revolution," but you're not sure where. Worse, every time you press C-s, the terminal
freezes up until you press C-q because of flow control problems. Instead of searching forward, search backward by moving the cursor to the bottom of the file with M-> and then pressing C-r.
Emacs: dickens.note (Fundamental)Bot
I-search backward:
As you type each character of the pattern Revolution, the cursor dances backward, matching the pattern as it grows longer and longer, until EMACS finds the word you seek:
Whenever any reference (however slight) is made here to the condition of the French people before or during the [R]evolution, 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 guide. Tavistock House November 1859 Emacs: dickens.note (Fundamental)Bot- I-search backward: Revol
Now try the query-replace feature. Move to the top of the file with M-<, and then type in M-x, which causes the notation to show up on the bottom status 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 **-Emacs: dickens.note (Fundamental)Top97Ä- M-x _
Then type the words query-replace and press Return. EMACS understands that you want to find all occurrences of a pattern and replace them with another. EMACS changes the prompt to this:
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 **-Emacs: dickens.note (Fundamental)Top- Query replace: _
Now type in the word that you want to replace. To cause confusion in the file, change French to Danish. Maybe A Tale of Two Cities really takes place in London and Copenhagen! To do this, type French and press Return. The prompt again changes to this:
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 **-Emacs: dickens.note (Fundamental)Top- Query replace French with: _
Enter Danish and again press Return.
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 **-Emacs: dickens.note (Fundamental)Top- Query replacing French with Danish:
It may not be completely obvious, but EMACS has found a match (immediately before the cursor) and is prompting you for what to do next. The choices here are summarized in Table 7.6.
Command |
Meaning |
|
y |
Change this occurrence of the pattern. |
|
n |
Don't change this occurrence, but look for another. |
|
q |
Don't change. Leave query-replace completely (you can also use Esc for this function). |
|
! |
Change this occurrence and all others in the file. |
Opt to make this change, and all other possible changes in the file, by pressing !. The screen changes to tell you that there were no more occurrences:
Whenever any reference (however slight) is made here to the condition of the Danish_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 **-Emacs: dickens.note (Fundamental)Top Done
Searching in EMACS is awkward, due in particular to the flow control problems that you may incur because of your terminal. However, searching and replacing with the query-replace command is much better and more powerful than the vi alternative. Your
assessment of EMACS all depends on what features you prefer.
Unlike vi and, indeed, most of UNIX, EMACS includes its own extensive built-in documentation and a tutorial to help you learn about using the package. As noted earlier, the entire help system is accessed by pressing C-h. Pressing C-h three times brings
up the general help menu screen. There is also an information browser called info (accessed by pressing C-h i) and a tutorial system you can start by pressing C-h t.
EMACS enthusiasts insist that the editor is modeless, but in fact it does have modes of its own. You used one just now, the query-replace mode. To obtain help on the current mode that you're working in, you can use C-h m.
Press C-h C-h C-h, and the entire screen is replaced with this:
You have typed C-h, the help character. Type a Help option:
A command-apropos. Give a substring, and see a list of commands
(functions interactively callable) that contain
that substring. See also the apropos command.
B dEscribe-bindings. Display table of all key bindings.
C dEscribe-key-briefly. Type a command key sequence;
it prints the function name that sequence runs.
F dEscribe-function. Type a function name and get documentation of it.
I info. The info documentation reader.
K dEscribe-key. Type a command key sequence;
it displays the full documentation.
L view-lossage. Shows last 100 characters you typed.
M dEscribe-mode. Print documentation of current major mode,
which dEscribes the commands peculiar to it.
N view-emacs-news. Shows emacs news file.
S dEscribe-syntax. Display contents of syntax table, plus explanations
T help-with-tutorial. Select the Emacs learn-by-doing tutorial.
V dEscribe-variable. Type name of a variable;
it displays the variable's documentation and value.
W where-is. Type command name; it prints which keystrokes
invoke that command.
**-Emacs: *Help* (Fundamental)Top
A B C F I K L M N S T V W C-c C-d C-n C-w or Space to scroll: _
What now? There are actually 17 different options from this point, as shown in Table 7.7.
Command |
Meaning |
|
A |
List all commands matching the specified word. |
|
B |
List all key mappings (EMACS calls them key bindings). |
|
C |
DEscribe any key sequence pressed, instead of doing it. |
|
F |
DEscribe the specified function. |
|
I |
Start up the info browser. |
|
K |
Fully dEscribe the result of a particular key sequence. |
|
L |
Show the last 100 characters you typed. |
|
M |
DEscribe the current mode you're in. |
|
S |
List a command syntax table. |
|
T |
Start the EMACS tutorial. |
|
V |
Define and dEscribe the specified variable. |
|
W |
Indicate what keystroke invokes a particular function. |
|
C-c |
EMACS copyright and distribution information. |
|
C-d |
EMACS ordering information. |
|
C-n |
Recent EMACS changes. |
|
C-w |
EMACS warranty. |
Choose K and then press M-< to see what that command really does. The first thing that happens after you enter K is that the table of help information vanishes, to be replaced by the original text. Then the prompt appears along the bottom:
of the Danish_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 **-Emacs: dickens.note (Fundamental)Top- DEscribe key:-
Pressing M-< brings up the desired information:
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 came 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
Emacs: dickens.note~ (Fundamental)Top-
beginning-of-buffer:
Move point to the beginning of the buffer; leave mark at previous position.
With arg N, put point N/10 of the way from the true beginning.
Don't use this in Lisp programs!
(goto-char (point-min)) is faster and does not set the mark.
Emacs: *Help* (Fundamental)All
Type C-x 1 to remove help window.
A quick C-x 1 removes the help information when you're done with it.
There is a considerable amount of help available in the EMACS editor. If you're interested in learning more about this editor, the online tutorial is a great place to start. Try C-h t to start it and go from there.
By this point it should be no surprise that there are about a million commands available within the EMACS editor, even though it can be a bit tricky to get to them. There are many file-related commands too, but this section focuses on just a few
essential commands so you can get around in the program. The EMACS help system can offer lots more. (Try using C-h a file to find out what functions are offered in your version of the program.)
To add the contents of a file to the current edit buffer, use the command C-x i. It will prompt for a filename. Pressing C-x C-w prompts for a file to write the buffer into, rather than the default file. To save to the default file, use C-x C-s (that
is, if you can: the C-s might again hang you up, just as it did when you tried to use it for searching). If that doesn't work, you can always use the alternative C-x s. To move to another file, use C-x C-f. (EMACS users never specify more than one filename
on the command line. They use C-x C-f to move between files instead). What's nice is that when you use the C-x C-f command, you load the contents of that file into another buffer, so you can zip quickly between files by using the C-x b command to switch
buffers.
Without leaving EMACS, press C-x C-f to read another file into the buffer. The system then prompts you as follows:
of the Danish 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 Emacs: dickens.note (Fundamental)Top Find file: ~/ _
Type buckaroo and the editor opens up a new buffer, moving you to that 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?" Emacs: buckaroo (Fundamental)All-
Now flip back to the other buffer with C-x b. When you enter that command, however, it doesn't automatically move you there. Instead it offers this prompt:
**-Emacs: buckaroo (Fundamental)All- Switch to buffer: (default dickens.note) _
When you press ?, you receive a split screen indicating what the possible answers are:
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?" **-Emacs: buckaroo (Fundamental)All Possible completions are: *Buffer List* *Help* *scratch* buckaroo dickens.note Emacs: *Completions* (Fundamental)All Switch to buffer: (default dickens.note) _
The default is okay, so press Return and go back to the Dickens file. One more C-x b; this time the default is buckaroo, so again press Return to move back.
You're in the buckaroo file, and you want to see what happens if you read dickens.note into this file. This is done easily. Move the cursor to the end of the file with M-> and then press C-x i, answering dickens.note to the prompt Insert file: ~/.
Pressing Return yields the following screen display:
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?"
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 came 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 posession
**-Emacs: buckaroo (Fundamental)Top-
It's time to quit and split. To do this, press C-x s and wait for an EMACS prompt or two. The first one displayed is this:
As the idea became familiar to me, it gradually shaped itself into its present form. Throughout its execution, it has had complete posession **-Emacs: buckaroo (Fundamental)Top Save file /users/taylor/buckaroo? (y or n) _
Answer y to save this muddled file. It returns you to the top of the file, and a quick C-x C-c drops you back to the system prompt.
This has only scratched the surface of EMACS, a fantastically powerful editor. The best way to learn more is to work through the online tutorial in the editor or to peruse the information available in the help system.
You have now learned quite a bit about the EMACS editor. Some capabilities exceed those of the vi editor, and some are considerably more confusing. Which of these editors you choose is up to you, and your choice should be based on your own preferences
for working on files. You should spend some time working with the editor you prefer to make sure you can create simple files and modify them without any problems.
In this section, you get to put on your programming hat and learn about a powerful command that can be customized infinitely and used for a wide variety of tasks. sed is a program for modifying information traveling through a UNIX pipeline.
I'm willing to bet that when you read about learning some UNIX programming tools in this section, you got anxious, your palms started to get sweaty, your fingers shook, and the little voice in your head said, "It's too late! We can use a pad and
paper! We don't need computers at all!"
Don't panic.
If you think about it, you've been programming all along in UNIX. When you enter a command to the shell, you're programming the shell to immediately perform the task specified. When you specify file redirection or build a pipe, you're really writing a
small UNIX program that the shell interprets and acts upon. Frankly, when you consider how many different commands you now know and how many different flags there are for each of those commands, you've got quite a set of programming tools under your belt
already. So onward!
With a | symbol called a pipe, and commands tied together called pipelines, is it any wonder that the information flowing down a pipeline is called a stream? For example, the command cat test | wc means that the cat command opens the file test and
streams it to the wc program, which counts the number of lines, words, and characters therein.
To modify the information in a pipeline, then, it seems reasonable to use a stream editor, and that's exactly what the sed command is! In fact, its name comes from its function: stream editor.
Here's the bad news. The sed command is built on an old editor called ed, the same editor that's responsible for the grep command. Remember? The global/regular expression/print eventually became grep. A microcosm of UNIX itself, commands to sed are
separated by a semicolon.
There are many different sed commands, but this section focuses on using sed to substitute one pattern for another and to extract ranges of lines from a file. The general format of the substitution command is: s/old/new/flags, where
old and new are the patterns you're working with, s is the abbreviation for the substitute command, and the two most helpful flags are g (to replace all occurrences globally on each line) and n (to tell sed to replace only the first n
occurrences of the pattern). By default, lines are listed to the screen, so a sed expression like 10q will cause the program to list the first 10 lines and then quit (making it an alternative to the command head -10). Deletion is similar: the
command is prefaced by one or two addresses in the file, reflecting a request to delete either all lines that match the specified address or all in the range of first to last.
The format of the sed command is sed followed by the expression in quotes and, optionally, the name of the file to read for input.
Here's an easy example. Use grep to extract some lines from the /etc/passwd file and replace all colons with a single space. The format of this command is to substitute each occurrence of : with a space, or s/:/ /:
% grep taylor /etc/passwd | sed -e 's/:/ /' taylorj ?:1048:1375:James Taylor:/users/taylorj:/bin/csh mtaylor ?:769:1375:Mary Taylor:/users/mtaylor:/usr/local/bin/tcsh dataylor ?:375:518:Dave Taylor,,,,:/users/dataylor:/usr/local/lib/msh taylorjr ?:203:1022:James Taylor:/users/taylorjr:/bin/csh taylorrj ?:662:1042:Robert Taylor:/users/taylorrj:/bin/csh taylorm ?:869:1508:Melanie Taylor:/users/taylorm:/bin/csh taylor ?:1989:1412:Dave Taylor:/users/taylor:/bin/csh
This doesn't quite do what you want. You neglected to append the global instruction to the sed command to ensure that it would replace all occurrences of the pattern on each line. Try it again, this time adding a g to the instruction.
% grep taylor /etc/passwd | sed -e 's/:/ /g' taylorj ? 1048 1375 James Taylor /users/taylorj /bin/csh mtaylor ? 769 1375 Mary Taylor /users/mtaylor /usr/local/bin/tcsh dataylor ? 375 518 Dave Taylor /users/dataylor /usr/local/lib/msh taylorjr ? 203 1022 James Taylor /users/taylorjr /bin/csh taylorrj ? 662 1042 Robert Taylor /users/taylorrj /bin/csh taylorm ? 869 1508 Melanie Taylor /users/taylorm /bin/csh taylor ? 1989 1412 Dave Taylor /users/taylor /bin/csh
A more sophisticated example of substitution with sed is to modify names, replacing all occurrences of Taylor with Tailor:
% grep taylor /etc/passwd | sed -e 's/Taylor/Tailor/g' taylorj:?:1048:1375:James Tailor:/users/taylorj:/bin/csh mtaylor:?:769:1375:Mary Tailor:/users/mtaylor:/usr/local/bin/tcsh dataylor:?:375:518:Dave Tailor:/users/dataylor:/usr/local/lib/msh taylorjr:?:203:1022:James Tailor:/users/taylorjr:/bin/csh taylorrj:?:662:1042:Robert Tailor:/users/taylorrj:/bin/csh taylorm:?:869:1508:Melanie Tailor:/users/taylorm:/bin/csh taylor:?:1989:1412:Dave Tailor:/users/taylor:/bin/csh
The colons have returned, which is annoying. Use the fact that a semicolon can separate multiple sed commands on the same line and try it one more time:
% grep taylor /etc/passwd | sed -e 's/Taylor/Tailor/g;s/:/ /g' taylorj ? 1048 1375 James Tailor /users/taylorj /bin/csh mtaylor ? 769 1375 Mary Tailor /users/mtaylor /usr/local/bin/tcsh dataylor ? 375 518 Dave Tailor /users/dataylor /usr/local/lib/msh taylorjr ? 203 1022 James Tailor /users/taylorjr /bin/csh taylorrj ? 662 1042 Robert Tailor /users/taylorrj /bin/csh taylorm ? 8692 1508 Melanie Tailor /users/taylorm /bin/csh taylor ? 1989 1412 Dave Tailor /users/taylor /bin/csh
This last sed command can be read as "each time you encounter the pattern Taylor replace it with Tailor, even if it occurs multiple times on each line. Then, each time you encounter a colon, replace it with a space."
Another example of using sed is to rewrite the output of the who command to be a bit more readable. Consider the results of entering who on your system:
% who strawmye ttyAc Nov 21 19:01 eiyo ttyAd Nov 21 17:40 tzhen ttyAg Nov 21 19:13 kmkernek ttyAh Nov 17 23:22 macedot ttyAj Nov 21 20:41 rpm ttyAk Nov 21 20:40 ypchen ttyAl Nov 21 18:20 kodak ttyAm Nov 21 20:43
The output is a bit confusing; sed can help:
% who | sed 's/tty/On Device /;s/Nov/Logged in November/' strawmye On Device Ac Logged in November 21 19:01 eiyo On Device Ad Logged in November 21 17:40 tzhen On Device Ag Logged in November 21 19:13 kmkernek On Device Ah Logged in November 17 23:22 macedot On Device Aj Logged in November 21 20:41 rpm On Device Ak Logged in November 21 20:40 ypchen On Device Al Logged in November 21 18:20 kodak On Device Am Logged in November 21 20:43
This time, each occurrence of the letters tty is replaced with the phrase On Device. Similarly, Nov is replaced with Logged in November.
The sed command can also be used to delete lines in the stream as it passes. The simplest version is to specify only the command:
% who | sed 'd' %
There's no output because the command matches all lines and deletes them. Instead, to delete just the first line, simply preface the d command with that line number:
% who | sed '1d' eiyo ttyAd Nov 21 17:40 tzhen ttyAg Nov 21 19:13 kmkernek ttyAh Nov 17 23:22 macedot ttyAj Nov 21 20:41 rpm ttyAk Nov 21 20:40 ypchen ttyAl Nov 21 18:20 kodak ttyAm Nov 21 20:43
To delete more than just the one line, specify the first and last lines to delete, separating them with a comma. The following deletes the first three lines:
% who | sed '1,3d' macedot ttyAj Nov 21 20:41 rpm ttyAk Nov 21 20:40 ypchen ttyAl Nov 21 18:20 kodak ttyAm Nov 21 20:43
There's more to deletion than that. You can also specify patterns by surrounding them with slashes, just the substitution pattern. To delete the entries in the who output between eiyo and rpm, the following would work:
% who | head -15 | sed '/eiyo/,/rpm/d' root console Nov 9 07:31 rick ttyAa Nov 21 20:58 brunnert ttyAb Nov 21 20:56 ypchen ttyAl Nov 21 18:20 kodak ttyAm Nov 21 20:43 wh ttyAn Nov 21 20:33 klingham ttyAp Nov 21 19:55 linet2 ttyAq Nov 21 20:17 mdps ttyAr Nov 21 20:11
You can use patterns in combination with numbers too, so if you wanted to delete the text from the first line to the line containing kmkernek, here's how you could do it:
% who | sed '1,/kmkernek/d' macedot ttyAj Nov 21 20:41 rpm ttyAk Nov 21 20:40 ypchen ttyAl Nov 21 18:20 kodak ttyAm Nov 21 20:43
Another aspect of sed is that the patterns are actually regular expressions. Don't be intimidated, though. If you understood the * and ? in filename wildcards, you've learned the key lesson of regular expressions: special characters can match zero or
more letters in the pattern. Regular expressions are slightly different from shell patterns, because regular expressions more powerful (though more confusing). Instead of using the ? to match a character, use the . character.
Within this context, it's rare that you need to look for patterns sufficiently complex to require a full regular expression, which is definitely good news. The only two characters you want to remember for regular expressions are ^, which is the
imaginary character before the first character of each line, and $, which is the character after the end of each line.
What does this mean? It means that you can use sed to list everyone reported by who that doesn't have s as the first letter of his or her account. You can also eliminate all blank lines from a file with sed. Return to the testme file:
% cat testme Archives/ OWL/ keylime.pie InfoWorld/ bin/ src/ Mail/ bitnet.mailing-lists.Z temp/ News/ drop.text.hqx testme Archives/ OWL/ keylime.pie InfoWorld/ bin/ src/ Mail/ bitnet.mailing-lists.Z temp/ News/ drop.text.hqx testme Archives/ OWL/ keylime.pie InfoWorld/ bin/ src/ Mail/ bitnet.mailing-lists.Z temp/ News/ drop.text.hqx testme
Now use sed to clean up this output.
% sed '/^$/d' < testme Archives/ OWL/ keylime.pie InfoWorld/ bin/ src/ Mail/ bitnet.mailing-lists.Z temp/ News/ drop.text.hqx testme Archives/ OWL/ keylime.pie InfoWorld/ bin/ src/ Mail/ bitnet.mailing-lists.Z temp/ News/ drop.text.hqx testme Archives/ OWL/ keylime.pie InfoWorld/ bin/ src/ Mail/ bitnet.mailing-lists.Z temp/ News/ drop.text.hqx testme %
These commands can be used in combination, of course; one sed command can be used to remove all blank lines, all lines that contain the word keylime, and substitute BinHex for each occurrence of hqx:
% cat testme | sed '/^$/d;/keylime/d;s/hqx/BinHex/g' InfoWorld/ bin/ src/ Mail/ bitnet.mailing-lists.Z temp/ News/ drop.text.BinHex testme InfoWorld/ bin/ src/ Mail/ bitnet.mailing-lists.Z temp/ News/ drop.text.BinHex testme InfoWorld/ bin/ src/ Mail/ bitnet.mailing-lists.Z temp/ News/ drop.text.BinHex testme %
If you've ever spent any time on an electronic network, you've probably seen either electronic mail or articles wherein the author responds to a previous article. Most commonly, all the lines of the original message are included, each prefixed by >.
It turns out that sed is the appropriate tool either to add a prefix to a group of lines or to remove a prefix from lines in a file:
% cat << EOF > sample Hey Tai! I've been looking for a music CD and none of the shops around here have a clue about it. I was wondering if you're going to have a chance to get into Tower Records in the next week or so? EOF % % sed 's/^/> /' < sample > sample2 % cat sample2 > Hey Tai! I've been looking for a music CD and none of > the shops around here have a clue about it. I was > wondering if you're going to have a chance to get into > Tower Records in the next week or so? % % cat sample2 | sed 's/^> //' Hey Tai! I've been looking for a music CD and none of the shops around here have a clue about it. I was wondering if you're going to have a chance to get into Tower Records in the next week or so? %
Recall that the caret (^) signifies the beginning of the line, so the first invocation of sed searches for the beginning of each line and replaces it with >, saving the output to the file sample2. The second use of sedwherein you remove the
prefixdoes the opposite search, finding all occurrences of "> " that are at the beginning of a line and replacing them with a null pattern (which is what you have when you have two slash delimiters without anything between them).
I've only scratched the surface of the sed command here. It's one of those commands where the more you learn about it, the more powerful you realize it is. But, paradoxically, the more you learn about it, the more you'll really want a graphical
interface to simplify your life.