A Tutorial Introduction to the UNIX Text Editor Brian W. Kernighan _A_B_S_T_R_A_C_T Almost all text input on the UNIX|- operating system is done with the text-editor This memoran- dum is a tutorial guide to help beginners get started with text editing. Although it does not cover everything, it does discuss enough for most users' day-to-day needs. This includes printing, appending, chang- ing, deleting, moving and inserting entire lines of text; reading and writing files; context searching and line addressing; the substitute com- mand; the global commands; and the use of special characters for advanced editing. _I_n_t_r_o_d_u_c_t_i_o_n _E_d is a ``text editor'', that is, an interactive pro- gram for creating and modifying ``text'', using directions provided by a user at a terminal. The text is often a docu- ment like this one, or a program or perhaps data for a pro- gram. This introduction is meant to simplify learning _e_d. The recommended way to learn _e_d is to read this document, simultaneously using _e_d to follow the examples, then to read the description in section I of the _P_r_o_g_r_a_m_m_e_r'_s _M_a_n_u_a_l, all the while experimenting with _e_d. (Solicitation of advice from experienced users is also useful.) Do the exercises! They cover material not completely discussed in the actual text. An appendix summarizes the commands. _D_i_s_c_l_a_i_m_e_r This is an introduction and a tutorial. For this _________________________ |- UNIX is a trademark of Bell Laboratories. August 9, 1987 USD:12-2 A Tutorial Introduction to the UNIX Text Editor reason, no attempt is made to cover more than a part of the facilities that _e_d offers (although this fraction includes the most useful and frequently used parts). When you have mastered the Tutorial, try _A_d_v_a_n_c_e_d _E_d_i_t_i_n_g _o_n _A_l_s_o, there is not enough space to explain basic procedures. We will assume that you know how to log on to and that you have at least a vague understanding of what a file is. For more on that, read _f_o_r _B_e_g_i_n_n_e_r_s. You must also know what character to type as the end- of-line on your particular terminal. This character is the key on most terminals. Throughout, we will refer to this character, whatever it is, as _G_e_t_t_i_n_g _S_t_a_r_t_e_d We'll assume that you have logged in to your system and it has just printed the prompt character, usually either a $ or a %. The easiest way to get _e_d is to type ed (followed by a return) You are now ready to go - _e_d is waiting for you to tell it what to do. _C_r_e_a_t_i_n_g _T_e_x_t - _t_h_e _A_p_p_e_n_d _c_o_m_m_a_n_d ``_a'' As your first problem, suppose you want to create some text starting from scratch. Perhaps you are typing the very first draft of a paper; clearly it will have to start some- where, and undergo modifications later. This section will show how to get some text in, just to get started. Later we'll talk about how to change it. When _e_d is first started, it is rather like working with a blank piece of paper - there is no text or informa- tion present. This must be supplied by the person using _e_d; it is usually done by typing in the text, or by reading it into _e_d from a file. We will start by typing in some text, and return shortly to how to read files. First a bit of terminology. In _e_d jargon, the text being worked on is said to be ``kept in a buffer.'' Think of the buffer as a work space, if you like, or simply as the information that you are going to be editing. In effect the buffer is like the piece of paper, on which we will write things, then change some of them, and finally file the whole thing away for another day. The user tells _e_d what to do to his text by typing instructions called ``commands.'' Most commands consist of a single letter, which must be typed in lower case. Each com- mand is typed on a separate line. (Sometimes the command is preceded by information about what line or lines of text are to be affected - we will discuss these shortly.) _E_d makes no response to most commands - there is no prompting or typing of messages like ``ready''. (This silence is preferred by August 9, 1987 A Tutorial Introduction to the UNIX Text Editor USD:12-3 experienced users, but sometimes a hangup for beginners.) The first command is _a_p_p_e_n_d, written as the letter a all by itself. It means ``append (or add) text lines to the buffer, as I type them in.'' Appending is rather like writ- ing fresh material on a piece of paper. So to enter lines of text into the buffer, just type an _a followed by a followed by the lines of text you want, like this: a Now is the time for all good men to come to the aid of their party. The only way to stop appending is to type a line that contains only a period. The ``'' is used to tell _e_d that you have finished appending. (Even experienced users forget that terminating ``'' sometimes. If _e_d seems to be ignoring you, type an extra line with just ``'' on it. You may then find you've added some garbage lines to your text, which you'll have to take out later.) After the append command has been done, the buffer will contain the three lines Now is the time for all good men to come to the aid of their party. The _a'' and ``'' aren't there, because they are not text. To add more text to what you already have, just issue another _a command, and continue typing. _E_r_r_o_r _M_e_s_s_a_g_e_s - ``?'' If at any time you make an error in the commands you type to _e_d, it will tell you by typing ? This is about as cryptic as it can be, but with practice, you can usually figure out how you goofed. _W_r_i_t_i_n_g _t_e_x_t _o_u_t _a_s _a _f_i_l_e - _t_h_e _W_r_i_t_e _c_o_m_m_a_n_d ``_w'' It's likely that you'll want to save your text for later use. To write out the contents of the buffer onto a file, use the _w_r_i_t_e command w followed by the filename you want to write on. This will copy the buffer's contents onto the specified file (destroying any previous information on the file). To save the text on a file named _j_u_n_k, for exam- ple, type w junk Leave a space between _w and the file name. _E_d will respond by printing the number of characters it wrote out. In this case, _e_d would respond with 68 (Remember that blanks and the return character at the end of each line are included in the character count.) Writing a file just makes a copy of the text - the buffer's contents are not disturbed, so you can go on adding lines to it. This is an important point. _E_d at all times works on a copy of a file, not the file itself. No change in the contents of a file takes place until you give a _w command. (Writing out the August 9, 1987 USD:12-4 A Tutorial Introduction to the UNIX Text Editor text onto a file from time to time as it is being created is a good idea, since if the system crashes or if you make some horrible mistake, you will lose all the text in the buffer but any text that was written onto a file is relatively safe.) _L_e_a_v_i_n_g _e_d - _t_h_e _Q_u_i_t _c_o_m_m_a_n_d ``_q'' To terminate a session with save the text you're work- ing on by writing it onto a file using the _w command, and then type the command q which stands for The system will respond with the prompt character $ or %). At this point your buffer vanishes, with all its text, which is why you want to write it out before quitting.|- _E_x_e_r_c_i_s_e _1: Enter _e_d and create some text using a . . . text . . . . Write it out using _w. Then leave _e_d with the _q command, and print the file, to see that everything worked. (To print a file, say pr filename or cat filename in response to the prompt character. Try both.) _R_e_a_d_i_n_g _t_e_x_t _f_r_o_m _a _f_i_l_e - _t_h_e _E_d_i_t _c_o_m_m_a_n_d ``_e'' A common way to get text into the buffer is to read it from a file in the file system. This is what you do to edit text that you saved with the _w command in a previous ses- sion. The _e_d_i_t command _e fetches the entire contents of a file into the buffer. So if you had saved the three lines ``Now is the time'', etc., with a _w command in an earlier session, the _e_d command e junk would fetch the entire con- tents of the file _j_u_n_k into the buffer, and respond 68 which is the number of characters in _j_u_n_k. _I_f _a_n_y_t_h_i_n_g _w_a_s _a_l_r_e_a_d_y _i_n _t_h_e _b_u_f_f_e_r, _i_t _i_s _d_e_l_e_t_e_d _f_i_r_s_t. If you use the _e command to read a file into the buffer, then you need not use a file name after a subsequent _w command; _e_d remembers the last file name used in an _e com- mand, and _w will write on this file. Thus a good way to operate is ed e file [editing session] w q This way, you can simply say _w from time to time, and be secure in the knowledge that if you got the file name right at the begin- ning, you are writing into the proper file each time. You can find out at any time what file name _e_d is remembering by typing the _f_i_l_e command _f. In this example, if you typed f _e_d would reply junk _________________________ |- Actually, will print ? if you try to quit without writing. At that point, write if you want; if not, another _q will get you out regardless. August 9, 1987 A Tutorial Introduction to the UNIX Text Editor USD:12-5 _R_e_a_d_i_n_g _t_e_x_t _f_r_o_m _a _f_i_l_e - _t_h_e _R_e_a_d _c_o_m_m_a_n_d ``_r'' Sometimes you want to read a file into the buffer without destroying anything that is already there. This is done by the _r_e_a_d command _r. The command r junk will read the file _j_u_n_k into the buffer; it adds it to the end of whatever is already in the buffer. So if you do a read after an edit: e junk r junk the buffer will contain _t_w_o copies of the text (six lines). Now is the time for all good men to come to the aid of their party. Now is the time for all good men to come to the aid of their party. Like the _w and _e commands, _r prints the number of characters read in, after the reading operation is complete. Generally speaking, _r is much less used than _e. _E_x_e_r_c_i_s_e _2: Experiment with the _e command - try reading and print- ing various files. You may get an error ?_n_a_m_e, where _n_a_m_e is the name of a file; this means that the file doesn't exist, typically because you spelled the file name wrong, or perhaps that you are not allowed to read or write it. Try alternately reading and appending to see that they work similarly. Verify that ed filename is exactly equivalent to ed e filename What does f filename do? _P_r_i_n_t_i_n_g _t_h_e _c_o_n_t_e_n_t_s _o_f _t_h_e _b_u_f_f_e_r - _t_h_e _P_r_i_n_t _c_o_m_m_a_n_d ``_p'' To _p_r_i_n_t or list the contents of the buffer (or parts of it) on the terminal, use the print command p The way this is done is as follows. Specify the lines where you want printing to begin and where you want it to end, separated by a comma, and followed by the letter _p. Thus to print the first two lines of the buffer, for example, (that is, lines 1 through 2) say 1,2p (starting line=1, ending line=2 p) _E_d will respond with Now is the time for all good men Suppose you want to print _a_l_l the lines in the buffer. You could use _1,_3_p as above if you knew there were exactly 3 lines in the buffer. But in general, you don't know how many there are, so what do you use for the ending line number? _E_d provides a shorthand symbol for ``line number of last line in buffer'' - the dollar sign $. Use it this way: 1,$p This will print _a_l_l the lines in the buffer (line 1 to last line.) If you want to stop the printing before it is finished, push the or Delete key; _e_d will type ? and wait for the next command. To print the _l_a_s_t line of the buffer, you could use $,$p but _e_d lets you abbreviate this to $p You can print any single line by typing the line number followed by a _p. Thus 1p produces the response Now is the time which is the first August 9, 1987 USD:12-6 A Tutorial Introduction to the UNIX Text Editor line of the buffer. In fact, _e_d lets you abbreviate even further: you can print any single line by typing _j_u_s_t the line number - no need to type the letter _p. So if you say $ _e_d will print the last line of the buffer. You can also use $ in combinations like $-1,$p which prints the last two lines of the buffer. This helps when you want to see how far you got in typing. _E_x_e_r_c_i_s_e _3: As before, create some text using the _a command and experiment with the _p command. You will find, for example, that you can't print line 0 or a line beyond the end of the buffer, and that attempts to print a buffer in reverse order by saying 3,1p don't work. _T_h_e _c_u_r_r_e_n_t _l_i_n_e - ``_D_o_t'' _o_r ``.'' Suppose your buffer still contains the six lines as above, that you have just typed 1,3p and _e_d has printed the three lines for you. Try typing just p (no line numbers) This will print to come to the aid of their party. which is the third line of the buffer. In fact it is the last (most recent) line that you have done anything with. (You just printed it!) You can repeat this _p command without line numbers, and it will continue to print line 3. The reason is that _e_d maintains a record of the last line that you did anything to (in this case, line 3, which you just printed) so that it can be used instead of an explicit line number. This most recent line is referred to by the shorthand symbol (pronounced ``dot''). Dot is a line number in the same way that $ is; it means exactly ``the current line'', or loosely, ``the line you most recently did something to.'' You can use it in several ways - one possibility is to say ,$p This will print all the lines from (including) the current line to the end of the buffer. In our example these are lines 3 through 6. Some commands change the value of dot, while others do not. The _p command sets dot to the number of the last line printed; the last command will set both and $ to 6. Dot is most useful when used in combinations like this one: +1 (or equivalently, +1p) This means ``print the next line'' and is a handy way to step slowly through a buffer. You can also say -1 (or -1p ) which means ``print the line _b_e_f_o_r_e the current line.'' This enables you to go backwards if you wish. Another useful one is August 9, 1987 A Tutorial Introduction to the UNIX Text Editor USD:12-7 something like -3,-1p which prints the previous three lines. Don't forget that all of these change the value of dot. You can find out what dot is at any time by typing = _E_d will respond by printing the value of dot. Let's summarize some things about the _p command and dot. Essentially _p can be preceded by 0, 1, or 2 line numbers. If there is no line number given, it prints the ``current line'', the line that dot refers to. If there is one line number given (with or without the letter _p), it prints that line (and dot is set there); and if there are two line numbers, it prints all the lines in that range (and sets dot to the last line printed.) If two line numbers are specified the first can't be bigger than the second (see Exercise 2.) Typing a single return will cause printing of the next line - it's equivalent to .+_1_p. Try it. Try typing a -; you will find that it's equivalent to .-_1_p. _D_e_l_e_t_i_n_g _l_i_n_e_s: _t_h_e ``_d'' _c_o_m_m_a_n_d Suppose you want to get rid of the three extra lines in the buffer. This is done by the _d_e_l_e_t_e command d Except that _d deletes lines instead of printing them, its action is similar to that of _p. The lines to be deleted are specified for _d exactly as they are for _p: _s_t_a_r_t_i_n_g _l_i_n_e, _e_n_d_i_n_g _l_i_n_e d Thus the command 4,$d deletes lines 4 through the end. There are now three lines left, as you can check by using 1,$p And notice that $ now is line 3! Dot is set to the next line after the last line deleted, unless the last line deleted is the last line in the buffer. In that case, dot is set to $. _E_x_e_r_c_i_s_e _4: Experiment with _a, _e, _r, _w, _p and _d until you are sure that you know what they do, and until you understand how dot, $, and line numbers are used. If you are adventurous, try using line numbers with _a, _r and _w as well. You will find that _a will append lines _a_f_t_e_r the line number that you specify (rather than after dot); that _r reads a file in _a_f_t_e_r the line number you specify (not necessarily at the end of the buffer); and that _w will write out exactly the lines you specify, not neces- sarily the whole buffer. These variations are sometimes handy. For instance you can insert a file at the beginning of a buffer by saying 0r filename and you can enter lines at the beginning of the buffer by saying 0a . . . _t_e_x_t . . . Notice that ._w is _v_e_r_y different from August 9, 1987 USD:12-8 A Tutorial Introduction to the UNIX Text Editor w _M_o_d_i_f_y_i_n_g _t_e_x_t: _t_h_e _S_u_b_s_t_i_t_u_t_e _c_o_m_m_a_n_d ``_s'' We are now ready to try one of the most important of all commands - the substitute command s This is the command that is used to change individual words or letters within a line or group of lines. It is what you use, for example, for correcting spelling mistakes and typing errors. Suppose that by a typing error, line 1 says Now is th time - the has been left off You can use _s to fix this up as follows: 1s/th/the/ This says: ``in line 1, substitute for the characters the characters To verify that it works will not print the result automatically) say p and get Now is the time which is what you wanted. Notice that dot must have been set to the line where the substitution took place, since the _p command printed that line. Dot is always set this way with the _s command. The general way to use the substitute command is _s_t_a_r_t_i_n_g-_l_i_n_e, _e_n_d_i_n_g-_l_i_n_e s/_c_h_a_n_g_e _t_h_i_s/_t_o _t_h_i_s/ Whatever string of characters is between the first pair of slashes is replaced by whatever is between the second pair, in _a_l_l the lines between _s_t_a_r_t_i_n_g-_l_i_n_e and _e_n_d_i_n_g-_l_i_n_e. Only the first occurrence on each line is changed, however. If you want to change _e_v_e_r_y occurrence, see Exercise 5. The rules for line numbers are the same as those for _p, except that dot is set to the last line changed. (But there is a trap for the unwary: if no substitution took place, dot is _n_o_t changed. This causes an error ? as a warning.) Thus you can say 1,$s/speling/spelling/ and correct the first spelling mistake on each line in the text. (This is useful for people who are consistent misspellers!) If no line numbers are given, the _s command assumes we mean ``make the substitution on line dot'', so it changes things only on the current line. This leads to the very common sequence s/something/something else/p which makes some correction on the current line, and then prints it, to make sure it worked out right. If it didn't, you can try again. (Notice that there is a _p on the same line as the _s command. With few exceptions, _p can follow any command; no other multi-command lines are legal.) It's also legal to say s/ . . . // which means ``change the first string of characters to i.e., remove them. This is useful for deleting extra words in a line or removing extra letters from words. For instance, if you had Nowxx is the time you can say s/xx//p to get Now is the time Notice that // (two adjacent slashes) means ``no characters'', not a blank. There _i_s a difference! (See below for another meaning of //.) August 9, 1987 A Tutorial Introduction to the UNIX Text Editor USD:12-9 _E_x_e_r_c_i_s_e _5: Experiment with the substitute command. See what hap- pens if you substitute for some word on a line with several occurrences of that word. For example, do this: a the other side of the coin s/the/on the/p You will get on the other side of the coin A substitute command changes only the first occurrence of the first string. You can change all occurrences by adding a _g (for ``global'') to the _s command, like this: s/ . . . / . . . /gp Try other characters instead of slashes to delimit the two sets of characters in the _s command - anything should work except blanks or tabs. (If you get funny results using any of the characters ^ $ [ * \ & read the section on ``Special Charac- ters''.) _C_o_n_t_e_x_t _s_e_a_r_c_h_i_n_g - ``/ . . . /'' With the substitute command mastered, you can move on to another highly important idea of _e_d - context searching. Suppose you have the original three line text in the buffer: Now is the time for all good men to come to the aid of their party. Suppose you want to find the line that con- tains so you can change it to Now with only three lines in the buffer, it's pretty easy to keep track of what line the word is on. But if the buffer contained several hundred lines, and you'd been making changes, deleting and rearrang- ing lines, and so on, you would no longer really know what this line number would be. Context searching is simply a method of specifying the desired line, regardless of what its number is, by specifying some context on it. The way to say ``search for a line that contains this particular string of characters'' is to type /_s_t_r_i_n_g _o_f _c_h_a_r_a_c_t_e_r_s _w_e _w_a_n_t _t_o _f_i_n_d/ For example, the _e_d command /their/ is a context search which is sufficient to find the desired line - it will locate the next occurrence of the characters between slashes (``their''). It also sets dot to that line and prints the line for verification: to come to the aid of their party. ``Next occurrence'' means that _e_d starts looking for the string at line .+_1, searches to the end of the buffer, then continues at line 1 and searches to line dot. (That is, the search ``wraps around'' from $ to 1.) It scans all the lines in the buffer until it either finds the desired line or gets back to dot again. If the given string of characters can't be found in any line, _e_d types the error message ? Otherwise it prints the line it found. You can do both the search for the desired line _a_n_d a August 9, 1987 USD:12-10 A Tutorial Introduction to the UNIX Text Editor substitution all at once, like this: /their/s/their/the/p which will yield to come to the aid of the party. There were three parts to that last command: context search for the desired line, make the substitution, print the line. The expression /_t_h_e_i_r/ is a context search expression. In their simplest form, all context search expressions are like this - a string of characters surrounded by slashes. Context searches are interchangeable with line numbers, so they can be used by themselves to find and print a desired line, or as line numbers for some other command, like _s. They were used both ways in the examples above. Suppose the buffer contains the three familiar lines Now is the time for all good men to come to the aid of their party. Then the _e_d line numbers /Now/+1 /good/ /party/-1 are all context search expressions, and they all refer to the same line (line 2). To make a change in line 2, you could say /Now/+1s/good/bad/ or /good/s/good/bad/ or /party/-1s/good/bad/ The choice is dictated only by conveni- ence. You could print all three lines by, for instance /Now/,/party/p or /Now/,/Now/+2p or by any number of similar combinations. The first one of these might be better if you don't know how many lines are involved. (Of course, if there were only three lines in the buffer, you'd use 1,$p but not if there were several hundred.) The basic rule is: a context search expression is _t_h_e _s_a_m_e _a_s a line number, so it can be used wherever a line number is needed. _E_x_e_r_c_i_s_e _6: Experiment with context searching. Try a body of text with several occurrences of the same string of characters, and scan through it using the same context search. Try using context searches as line numbers for the sub- stitute, print and delete commands. (They can also be used with _r, _w, and _a.) Try context searching using ?_t_e_x_t? instead of /_t_e_x_t/. This scans lines in the buffer in reverse order rather than normal. This is sometimes useful if you go too far while looking for some string of characters - it's an easy way to back up. (If you get funny results with any of the characters ^ $ [ * \ & read the section on ``Special Charac- ters''.) _E_d provides a shorthand for repeating a context search for the same string. For example, the _e_d line number /string/ will find the next occurrence of _s_t_r_i_n_g. It often August 9, 1987 A Tutorial Introduction to the UNIX Text Editor USD:12-11 happens that this is not the desired line, so the search must be repeated. This can be done by typing merely // This shorthand stands for ``the most recently used context search expression.'' It can also be used as the first string of the substitute command, as in /string1/s//string2/ which will find the next occurrence of _s_t_r_i_n_g_1 and replace it by _s_t_r_i_n_g_2. This can save a lot of typing. Similarly ?? means ``scan backwards for the same expression.'' _C_h_a_n_g_e _a_n_d _I_n_s_e_r_t - ``_c'' _a_n_d ``_i'' This section discusses the _c_h_a_n_g_e command c which is used to change or replace a group of one or more lines, and the _i_n_s_e_r_t command i which is used for inserting a group of one or more lines. ``Change'', written as c is used to replace a number of lines with different lines, which are typed in at the termi- nal. For example, to change lines .+_1 through $ to some- thing else, type .+1,$c . . . _t_y_p_e _t_h_e _l_i_n_e_s _o_f _t_e_x_t _y_o_u _w_a_n_t _h_e_r_e . . . The lines you type between the _c command and the . will take the place of the original lines between start line and end line. This is most useful in replacing a line or several lines which have errors in them. If only one line is specified in the _c command, then just that line is replaced. (You can type in as many replacement lines as you like.) Notice the use of . to end the input - this works just like the . in the append com- mand and must appear by itself on a new line. If no line number is given, line dot is replaced. The value of dot is set to the last line you typed in. ``Insert'' is similar to append - for instance /string/i . . . _t_y_p_e _t_h_e _l_i_n_e_s _t_o _b_e _i_n_s_e_r_t_e_d _h_e_r_e . . . will insert the given text _b_e_f_o_r_e the next line that con- tains ``string''. The text between _i and . is _i_n_s_e_r_t_e_d _b_e_f_o_r_e the specified line. If no line number is specified dot is used. Dot is set to the last line inserted. _E_x_e_r_c_i_s_e _7: ``Change'' is rather like a combination of delete fol- lowed by insert. Experiment to verify that _s_t_a_r_t, _e_n_d d i . . . _t_e_x_t . . . is almost the same as _s_t_a_r_t, _e_n_d c . . . _t_e_x_t . . . These are not _p_r_e_c_i_s_e_l_y the same if line $ gets deleted. Check this out. What is dot? August 9, 1987 USD:12-12 A Tutorial Introduction to the UNIX Text Editor Experiment with _a and _i, to see that they are similar, but not the same. You will observe that _l_i_n_e-_n_u_m_b_e_r a . . . _t_e_x_t . . . appends _a_f_t_e_r the given line, while _l_i_n_e-_n_u_m_b_e_r i . . . _t_e_x_t . . . inserts _b_e_f_o_r_e it. Observe that if no line number is given, _i inserts before line dot, while _a appends after line dot. _M_o_v_i_n_g _t_e_x_t _a_r_o_u_n_d: _t_h_e ``_m'' _c_o_m_m_a_n_d The move command _m is used for cutting and pasting - it lets you move a group of lines from one place to another in the buffer. Suppose you want to put the first three lines of the buffer at the end instead. You could do it by say- ing: 1,3w temp $r temp 1,3d (Do you see why?) but you can do it a lot easier with the _m command: 1,3m$ The general case is _s_t_a_r_t _l_i_n_e, _e_n_d _l_i_n_e m _a_f_t_e_r _t_h_i_s _l_i_n_e Notice that there is a third line to be specified - the place where the moved stuff gets put. Of course the lines to be moved can be specified by context searches; if you had First paragraph . . . end of first paragraph. Second paragraph . . . end of second paragraph. you could reverse the two paragraphs like this: /Second/,/end of second/m/First/-1 Notice the -_1: the moved text goes _a_f_t_e_r the line mentioned. Dot gets set to the last line moved. _T_h_e _g_l_o_b_a_l _c_o_m_m_a_n_d_s ``_g'' _a_n_d ``_v'' The _g_l_o_b_a_l command _g is used to execute one or more _e_d commands on all those lines in the buffer that match some specified string. For example g/peling/p prints all lines that contain _p_e_l_i_n_g. More usefully, g/peling/s//pelling/gp makes the substitution everywhere on the line, then prints each corrected line. Compare this to 1,$s/peling/pelling/gp which only prints the last line substituted. Another subtle difference is that the _g command does not give a ? if _p_e_l_- _i_n_g is not found where the _s command will. There may be several commands (including _a, _c, _i, _r, _w, but not _g); in that case, every line except the last must end with a backslash _\: g/xxx/-1s/abc/def/\ +2s/ghi/jkl/\ - 2,p makes changes in the lines before and after each line that contains _x_x_x, then prints all three lines. The _v command is the same as _g, except that the com- mands are executed on every line that does _n_o_t match the string following _v: v/ /d deletes every line that does not contain a blank. _S_p_e_c_i_a_l _C_h_a_r_a_c_t_e_r_s You may have noticed that things just don't work right August 9, 1987 A Tutorial Introduction to the UNIX Text Editor USD:12-13 when you used some characters like , *, $, and others in context searches and the substitute command. The reason is rather complex, although the cure is simple. Basically, _e_d treats these characters as special, with special meanings. For instance, _i_n _a _c_o_n_t_e_x_t _s_e_a_r_c_h _o_r _t_h_e _f_i_r_s_t _s_t_r_i_n_g _o_f _t_h_e _s_u_b_s_t_i_t_u_t_e _c_o_m_m_a_n_d _o_n_l_y, means ``any character,'' not a period, so /xy/ means ``a line with an _x, _a_n_y _c_h_a_r_a_c_t_e_r, and a _y,'' _n_o_t just ``a line with an _x, a period, and a _y.'' A complete list of the spe- cial characters that can cause trouble is the following: ^ $ [ * \ _W_a_r_n_i_n_g: The backslash character _\ is spe- cial to _e_d. For safety's sake, avoid it where possible. If you have to use one of the special characters in a substi- tute command, you can turn off its magic meaning temporarily by preceding it with the backslash. Thus s/\\\\*/backslash dot star/ will change _\.* into ``backslash dot star''. Here is a hurried synopsis of the other special charac- ters. First, the circumflex ^ signifies the beginning of a line. Thus /^string/ finds _s_t_r_i_n_g only if it is at the beginning of a line: it will find string but not the string... The dollar-sign $ is just the opposite of the circumflex; it means the end of a line: /string$/ will only find an occurrence of _s_t_r_i_n_g that is at the end of some line. This implies, of course, that /^string$/ will find only a line that contains just _s_t_r_i_n_g, and /^$/ finds a line containing exactly one character. The character ., as we mentioned above, matches any- thing; /xy/ matches any of x+y x-y x y xy This is useful in conjunction with *, which is a repetition character; _a* is a shorthand for ``any number of _a's,'' so .* matches any number of anythings. This is used like this: s/*/stuff/ which changes an entire line, or s/*,// which deletes all characters in the line up to and including the last comma. (Since .* finds the longest possible match, this goes up to the last comma.) [ is used with ] to form ``character classes''; for example, /[0123456789]/ matches any single digit - any one of the characters inside the braces will cause a match. This can be abbreviated to [_0-_9]. Finally, the & is another shorthand character - it is used only on the right-hand part of a substitute command where it means ``whatever was matched on the left-hand side''. It is used to save typing. Suppose the current line contained Now is the time and you wanted to put parentheses around it. You could just retype the line, but this is tedious. Or you could say s/^/(/ s/$/)/ using your knowledge of ^ and $. But the easiest way uses the &: s/*/(&)/ This says ``match the whole line, and replace it by itself surrounded by parentheses.'' The & can be used August 9, 1987 USD:12-14 A Tutorial Introduction to the UNIX Text Editor several times in a line; consider using s/*/&? &!!/ to pro- duce Now is the time? Now is the time!! You don't have to match the whole line, of course: if the buffer contains the end of the world you could type /world/s//& is at hand/ to produce the end of the world is at hand Observe this expression carefully, for it illus- trates how to take advantage of _e_d to save typing. The string /_w_o_r_l_d/ found the desired line; the shorthand // found the same word in the line; and the & saves you from typing it again. The & is a special character only within the replace- ment text of a substitute command, and has no special mean- ing elsewhere. You can turn off the special meaning of & by preceding it with a _\: s/ampersand/\&/ will convert the word ``ampersand'' into the literal symbol & in the current line. _S_u_m_m_a_r_y _o_f _C_o_m_m_a_n_d_s _a_n_d _L_i_n_e _N_u_m_b_e_r_s The general form of _e_d commands is the command name, perhaps preceded by one or two line numbers, and, in the case of _e, _r, and _w, followed by a file name. Only one com- mand is allowed per line, but a _p command may follow any other command (except for _e, _r, _w and _q). _a: Append, that is, add lines to the buffer (at line dot, unless a different line is specified). Appending continues until is typed on a new line. Dot is set to the last line appended. _c: Change the specified lines to the new text which follows. The new lines are terminated by a , as with _a. If no lines are specified, replace line dot. Dot is set to last line changed. _d: Delete the lines specified. If none are specified, delete line dot. Dot is set to the first undeleted line, unless $ is deleted, in which case dot is set to $. _e: Edit new file. Any previous contents of the buffer are thrown away, so issue a _w beforehand. _f: Print remembered filename. If a name follows _f the remembered name will be set to it. _g: The command g/---/commands will execute the commands on those lines that contain ---, which can be any context search expression. August 9, 1987 A Tutorial Introduction to the UNIX Text Editor USD:12-15 _i: Insert lines before specified line (or dot) until a is typed on a new line. Dot is set to last line inserted. _m: Move lines specified to after the line named after _m. Dot is set to the last line moved. _p: Print specified lines. If none specified, print line dot. A single line number is equivalent to _p. A single return prints .+_1, the next line. _q: Quit Wipes out all text in buffer if you give it twice in a row without first giving a _w command. _r: Read a file into buffer (at end unless specified else- where.) Dot set to last line read. _s: The command s/string1/string2/ substitutes the characters _s_t_r_i_n_g_1 into _s_t_r_i_n_g_2 in the specified lines. If no lines are specified, make the substitution in line dot. Dot is set to last line in which a substitution took place, which means that if no substitution took place, dot is not changed. _s changes only the first occurrence of _s_t_r_i_n_g_1 on a line; to change all of them, type a _g after the final slash. _v: The command v/---/commands executes _c_o_m_m_a_n_d_s on those lines that _d_o _n_o_t contain ---. _w: Write out buffer onto a file. Dot is not changed. .=: Print value of dot. = by itself prints the value of $.) !: The line !command-line causes _c_o_m_m_a_n_d-_l_i_n_e to be executed as a command. /-----/: Context search. Search for next line which con- tains this string of characters. Print it. Dot is set to the line where string was found. Search starts at .+_1, wraps around from $ to 1, and continues to dot, if neces- sary. ?-----?: Context search in reverse direction. Start search at .-_1, scan to 1, wrap around to $. August 9, 1987