# To unbundle, run this file echo e.mac sed 's/.//' >e.mac <<'//GO.SYSIN DD e.mac' -.ds . \&\s+2.\s0\& -.de UC -\&\\$3\s-1\\$1\s0\\$2 -.. -.de UL -.if t \&\\$3\f3\\$1\f1\\$2 -.if n \&\\$3\f2\\$1\f1\\$2 -.. -.de IT -\&\\$3\f2\\$1\fP\\$2 -.. -.de UI -\f3\\$1\fI\\$2\fR\\$3 -.. -.de P1 -.if n .ls 1 -.nf -.if n .ta 5 10 15 20 25 30 35 40 45 50 55 60 -.if t .ta .3i .6i .9i 1.2i 1.5i 1.8i -.tr -\- -. use first argument as indent if present -.if \\n(.$ .DS I \\$1 -.if !\\n(.$ .DS I 5 -.bd 1 2 -.. -.de P2 -.br -.bd 1 2 -.DE -.bd 1 -.tr -- -.if n .ls 2 -.. -.hy 14 -. 2=not last lines; 4= no -xx; 8=no xx- -.tr *\(** -.nr PI .2i //GO.SYSIN DD e.mac echo e0 sed 's/.//' >e0 <<'//GO.SYSIN DD e0' -.RP -.TL -A Tutorial Introduction to the \s-2UNIX\s+2 Text Editor -.AU -Brian W. Kernighan -.AI -.MH -.AB -.PP -Almost all text input on -the -.UX -operating system -is done with -the text-editor -.IT ed . -This memorandum is a tutorial guide -to help beginners get started -with text editing. -.PP -Although it does not cover everything, -it does discuss enough for most users' -day-to-day needs. -This includes -printing, appending, changing, deleting, moving and inserting entire lines of text; -reading and writing files; -context searching and line addressing; -the substitute command; -the global commands; -and the use of special characters for advanced editing. -.AE //GO.SYSIN DD e0 echo e1 sed 's/.//' >e1 <<'//GO.SYSIN DD e1' -.nr PS 9 -.nr VS 11 -.if t .2C -.SH -Introduction -.PP -.ul -Ed -is a ``text editor'', that is, an interactive program -for creating and modifying ``text'', -using directions provided by a user at -a terminal. -The text is often a document -like this one, -or a program -or perhaps data for a program. -.PP -This introduction is meant to simplify learning -.ul -ed. -The recommended way to learn -.ul -ed -is to read this document, -simultaneously using -.ul -ed -to follow the examples, -then to read the description in section I of the -.ul -.UC UNIX -.ul -Programmer's Manual, -all the while -experimenting with -.ul -ed. -(Solicitation of advice from experienced users is also useful.) -.PP -Do the exercises! -They cover material not completely discussed -in the actual text. -An appendix summarizes the commands. -.SH -Disclaimer -.PP -This is an introduction and a tutorial. -For this reason, no attempt is made to -cover more than a part of the facilities that -.ul -ed -offers -(although this fraction includes the most useful and frequently used -parts). -When you have mastered the Tutorial, -try -.ul -Advanced Editing on -.ul -.UC UNIX . -Also, -there is not enough space to explain basic -.UC UNIX -procedures. -We will assume that you know how to log on to -.UC UNIX , -and that you have at least a vague understanding -of what a file is. -For more on that, read -.ul -.UC UNIX -.ul -for Beginners. -.PP -You must also know what character to type as the end-of-line -on your particular terminal. -This character is the -.UC RETURN -key on most terminals. -Throughout, we will refer to this character, -whatever it is, -as -.UC RETURN . -.SH -Getting Started -.PP -We'll assume that you have logged in to -your system -and it has just printed the prompt character, -usually either a -.UL $ -or a -.UL % . -The -easiest way to get -.ul -ed -is to type -.P1 -ed (followed by a return) -.P2 -You are now ready to go \- -.ul -ed -is waiting for you to tell it what to do. -.SH -Creating Text \- the Append command ``a'' -.PP -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 -somewhere, 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. -.PP -When -.ul -ed -is first started, it is rather like working -with a blank piece of paper \- there is no text -or information present. -This must be supplied by the person using -.ul -ed; -it is usually done -by typing in the text, or by reading it into -.ul -ed -from a -file. -We will start by typing in some text, and return shortly to how to -read files. -.PP -First a bit of terminology. -In -.ul -ed -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. -.PP -The user tells -.ul -ed -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 command 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.) -.ul -Ed -makes no response -to most commands \- there is no prompting -or typing of messages like ``ready''. -(This silence is preferred -by experienced users, but sometimes a hangup for beginners.) -.PP -The first command is -.ul -append, -written as the letter -.P1 -a -.P2 -all -by itself. -It means ``append (or add) text lines to the buffer, -as I type them in.'' -Appending is rather like -writing fresh material on a piece of paper. -.PP -So to enter lines of text into the buffer, -just type an -.UL a -followed by a -.UC RETURN , -followed by the lines of text you want, like this: -.P1 -a -Now is the time -for all good men -to come to the aid of their party. -\*. -.P2 -.PP -The only way to stop appending is to type a -line that contains only a period. -The ``\*.'' is used -to tell -.ul -ed -that you have finished appending. -(Even experienced users forget that terminating ``\*.'' -sometimes. -If -.ul -ed -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.) -.PP -After the append command has been done, the buffer will -contain the three lines -.P1 -Now is the time -for all good men -to come to the aid of their party. -.P2 -The -.UL a '' `` -and ``\*.'' aren't there, because they are -not text. -.PP -To add more text to what you already have, -just issue another -.UL a -command, and continue typing. -.SH -Error Messages \- ``?'' -.PP -If at any time you make an error in the commands you type to -.ul -ed, -it will tell you by typing -.P1 -? -.P2 -This is about as cryptic as it can be, -but with practice, you can usually -figure out how you goofed. //GO.SYSIN DD e1 echo e2 sed 's/.//' >e2 <<'//GO.SYSIN DD e2' -.SH -Writing text out as a file \- the Write command ``w'' -.PP -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 -.ul -write -command -.P1 -w -.P2 -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 -.UL junk , -for example, type -.P1 -w junk -.P2 -Leave a space between -.UL w -and the file name. -.ul -Ed -will respond by printing -the number of characters it wrote out. -In this case, -.ul -ed -would respond with -.P1 -68 -.P2 -(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. -.ul -Ed -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 -.UL w -command. -(Writing out the 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.) -.SH -Leaving ed \- the Quit command ``q'' -.PP -To terminate a session with -.IT ed , -save the text you're working on -by writing it onto a file using the -.UL w -command, -and then type the command -.P1 -q -.P2 -which -stands for -.IT quit . -The system will respond with -the prompt character -.UL $ "" ( -or -.UL % ). -At -this point your buffer vanishes, with all its text, -which is why you want to write it out before quitting.\(dg -.FS -\(dg Actually, -.IT ed -will print -.UL ? -if you try to quit without writing. -At that point, write if you want; -if not, another -.UL q -will get you out regardless. -.FE -.SH -Exercise 1: -.PP -Enter -.ul -ed -and -create some text using -.P1 -a -\&. . . text . . . -\&\fB.\fR -.P2 -Write it out using -.UL w . -Then leave -.ul -ed -with the -.UL q -command, and print the file, -to see that everything worked. -(To print a file, say -.P1 -pr filename -.P2 -or -.P1 -cat filename -.P2 -in response to -the prompt character. -Try both.) -.SH -Reading text from a file \- the Edit command ``e'' -.PP -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 -.UL w -command in a previous session. -The -.ul -edit -command -.UL 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 -.UL w -command in an earlier session, -the -.ul -ed -command -.P1 -e junk -.P2 -would fetch the entire contents of the file -.UL junk -into the buffer, and respond -.P1 -68 -.P2 -which is the number of characters in -.UL junk . -.ul -If anything was already in the buffer, it is deleted first. -.PP -If you use the -.UL e -command to read a file into the buffer, -then you need not use a file name after a subsequent -.UL w -command; -.ul -ed -remembers the last file name used in an -.UL e -command, -and -.UL w -will write on this file. -Thus a good way to operate is -.P1 -ed -e file -[editing session] -w -q -.P2 -This way, you can simply say -.UL w -from time to time, -and be secure in the knowledge that -if you got the file name right at the beginning, -you are writing into the proper file each time. -.PP -You can find out at any time what file name -.ul -ed -is remembering by typing the -.ul -file -command -.UL f . -In this example, -if you typed -.P1 -f -.P2 -.ul -ed -would reply -.P1 -junk -.P2 -.SH -Reading text from a file \- the Read command ``r'' -.PP -Sometimes you want to read a file into the buffer -without destroying anything that is already there. -This is done by the -.ul -read -command -.UL r . -The command -.P1 -r junk -.P2 -will read the file -.UL junk -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: -.P1 -e junk -r junk -.P2 -the buffer will contain -.ul -two -copies of the text (six lines). -.P1 -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. -.P2 -Like the -.UL w -and -.UL e -commands, -.UL r -prints -the -number of characters read in, after the reading operation is complete. -.PP -Generally speaking, -.UL r -is much less used than -.UL e . -.SH -Exercise 2: -.PP -Experiment with the -.UL e -command \- -try reading and printing various files. -You may get an error -.UL ?name , -where -.UL name -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 -.P1 -ed filename -.P2 -is exactly equivalent to -.P1 -ed -e filename -.P2 -What does -.P1 -f filename -.P2 -do? -.SH -Printing the contents of the buffer \- the Print command ``p'' -.PP -To -.ul -print -or list the contents of the buffer (or parts -of it) on the terminal, use the print command -.P1 -p -.P2 -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 -.UL p . -Thus to print the first two lines of the buffer, for -example, (that is, lines 1 through 2) say -.P1 -1,2p (starting line=1, ending line=2 p) -.P2 -.ul -Ed -will respond with -.P1 -Now is the time -for all good men -.P2 -.PP -Suppose you want to print -.ul -all -the lines in the buffer. -You could use -.UL 1,3p -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? -.ul -Ed -provides a shorthand symbol for ``line number of -last line in buffer'' \- the dollar sign -.UL $ . -Use it this -way: -.P1 -1,$p -.P2 -This will print -.ul -all -the lines in the buffer (line 1 to last line.) -If you want to stop the printing before it is finished, -push the -.UC DEL -or Delete key; -.ul -ed -will type -.P1 -? -.P2 -and wait for the next command. -.PP -To print the -.ul -last -line of the buffer, you could use -.P1 -$,$p -.P2 -but -.ul -ed -lets you abbreviate this to -.P1 -$p -.P2 -You can print any single line by typing the line -number followed by a -.UL p . -Thus -.P1 -1p -.P2 -produces the response -.P1 -Now is the time -.P2 -which is the first line of the buffer. -.PP -In fact, -.ul -ed -lets you abbreviate even further: -you can print any single line by typing -.ul -just -the line number \- no need to type the letter -.UL p . -So if you say -.P1 -$ -.P2 -.ul -ed -will print the last line of the buffer. -.PP -You can also use -.UL $ -in combinations like -.P1 -$\-1,$p -.P2 -which prints the last two lines of the buffer. -This helps when you want to see how far you got in typing. -.SH -Exercise 3: -.PP -As before, create some text using the -.UL a -command and -experiment with the -.UL 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 -.P1 -3,1p -.P2 -don't work. //GO.SYSIN DD e2 echo e3 sed 's/.//' >e3 <<'//GO.SYSIN DD e3' -.SH -The current line \- ``Dot'' or ``.'' -.PP -Suppose your buffer still contains the six lines as above, -that you have just typed -.P1 -1,3p -.P2 -and -.ul -ed -has printed the three lines for you. -Try typing just -.P1 -p (no line numbers) -.P2 -This will print -.P1 -to come to the aid of their party. -.P2 -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 -.UL p -command without line numbers, and -it will continue to print line 3. -.PP -The reason is that -.ul -ed -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 -.P1 -\&\*. (pronounced ``dot''). -.P2 -Dot is a line number in the same way that -.UL $ -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 -.P1 -\&\*.,$p -.P2 -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. -.PP -Some commands change the value of dot, while others do not. -The -.UL p -command sets dot to the number of the last line printed; -the last command will -set both -\*. -and -.UL $ -to 6. -.PP -Dot is most useful when used in combinations like this one: -.P1 -\&\*.+1 (or equivalently, \*.+1p) -.P2 -This means ``print the next line'' and is a handy way to step -slowly through a buffer. -You can also say -.P1 -\&\*.\-1 (or \*.\-1p ) -.P2 -which means ``print the line -.ul -before -the current line.'' -This enables you to go backwards if you wish. -Another useful one is something like -.P1 -\&\*.\-3,\*.\-1p -.P2 -which prints the previous three lines. -.PP -Don't forget that all of these change the value of dot. -You can find out what dot is at any time by typing -.P1 -\&\*.= -.P2 -.ul -Ed -will respond by printing the value of dot. -.PP -Let's summarize some things about the -.UL p -command -and dot. -Essentially -.UL 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 -.UL 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.) -.PP -Typing a single return will cause printing of the next line \- -it's -equivalent to -.UL .+1p . -Try it. -Try typing -a -.UL \- ; -you will find that -it's equivalent to -.UL .\-1p . -.SH -Deleting lines: the ``d'' command -.PP -Suppose you want to get rid of the three extra lines in the buffer. -This is done by the -.ul -delete -command -.P1 -d -.P2 -Except that -.UL d -deletes lines instead of printing them, -its action is similar to that of -.UL p . -The lines to be deleted are specified for -.UL d -exactly as they are for -.UL p : -.P1 -\fIstarting line, ending line\fP d -.P2 -Thus the command -.P1 -4,$d -.P2 -deletes lines 4 through the end. -There are now three lines left, as you can check by using -.P1 -1,$p -.P2 -And notice that -.UL $ -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 -.UL $ . -.SH -Exercise 4: -.PP -Experiment with -.UL a , -.UL e , -.UL r , -.UL w , -.UL p -and -.UL d -until you are sure that you -know what they do, and until you understand how dot, -.UL $ , -and -line numbers are used. -.PP -If you are adventurous, try using line numbers with -.UL a , -.UL r -and -.UL w -as well. -You will find that -.UL a -will append lines -.ul -after -the line number that you specify (rather than after dot); that -.UL r -reads -a file in -.ul -after -the line number you specify (not necessarily -at the end of the buffer); and that -.UL w -will write out exactly the lines -you specify, not necessarily the whole buffer. -These variations are sometimes handy. -For instance you can insert a file at the beginning of a buffer -by saying -.P1 -0r filename -.P2 -and you can enter lines at the beginning of the buffer -by saying -.P1 -0a -\&. . . \fItext\fP . . . -\*. -.P2 -Notice that -.UL .w -is -.ul -very -different from -.P1 -\*. -w -.P2 -.SH -Modifying text: the Substitute command ``s'' -.PP -We are now ready to try one of the most important -of all commands \- the substitute command -.P1 -s -.P2 -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. -.PP -Suppose that by a typing error, line 1 says -.P1 -Now is th time -.P2 -\- the -.IT e -has been left off -.IT the . -You can use -.UL s -to fix this up as follows: -.P1 -1s/th/the/ -.P2 -This says: ``in line 1, substitute for the characters -.IT th -the characters -.IT the .'' -To verify -that it works -.IT ed "" ( -will not print -the result automatically) say -.P1 -p -.P2 -and get -.P1 -Now is the time -.P2 -which is what you wanted. -Notice that dot must have been set to the line -where the substitution took place, since the -.UL p -command -printed that line. -Dot is always set this way with the -.UL s -command. -.PP -The general way to use the substitute command is -.P1 -\fIstarting\(hyline, ending\(hyline\fP s/\fIchange this\fP/\fIto this\fP/ -.P2 -Whatever string of characters is between the first pair of -slashes is replaced by whatever is between the second pair, -in -.ul -all -the lines between -.ul -starting-line -and -.ul -ending-line. -Only the first occurrence on each line is changed, however. -If you want to change -.ul -every -occurrence, see Exercise 5. -The rules for line numbers are the same as those for -.UL 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 -.ul -not -changed. -This causes an error -.UL ? -as a warning.) -.PP -Thus you can say -.P1 -1,$s/speling/spelling/ -.P2 -and correct the first spelling mistake -on each line -in the text. -(This is useful for people who are consistent -misspellers!) -.PP -If no line numbers are given, the -.UL 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 -.P1 -s/something/something else/p -.P2 -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 -.UL p -on the same line as the -.UL s -command. -With few exceptions, -.UL p -can follow any command; -no other multi-command lines are legal.) -.PP -It's also legal to say -.P1 -s/ . . . // -.P2 -which means ``change the first -string of characters to -.IT nothing '', `` -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 -.P1 -Nowxx is the time -.P2 -you can say -.P1 -s/xx//p -.P2 -to get -.P1 -Now is the time -.P2 -Notice that -.UL // -(two adjacent slashes) means ``no characters'', not a blank. -There -.ul -is -a difference! -(See below for another meaning of -.UL // .) //GO.SYSIN DD e3 echo e4 sed 's/.//' >e4 <<'//GO.SYSIN DD e4' -.SH -Exercise 5: -.PP -Experiment with the substitute command. -See what happens if you -substitute for some word on a line with several occurrences of that word. -For example, do this: -.P1 -a -the other side of the coin -\*. -s/the/on the/p -.P2 -You will get -.P1 -on the other side of the coin -.P2 -A substitute command changes only the first occurrence of the first string. -You can change all occurrences by adding a -.UL g -(for ``global'') -to the -.UL s -command, like this: -.P1 -s/ . . . / . . . /gp -.P2 -Try other characters instead of slashes to delimit the two sets -of characters in the -.UL s -command \- anything should work -except blanks or tabs. -.PP -(If you get funny results using any of the characters -.P1 -^ \*. $ [ * \e & -.P2 -read the section on ``Special Characters''.) -.SH -Context searching \- ``/ . . . /'' -.PP -With the substitute command mastered, you can move on to -another highly important idea of -.ul -ed -\- context searching. -.PP -Suppose you have the original three line text in the buffer: -.P1 -Now is the time -for all good men -to come to the aid of their party. -.P2 -Suppose you want to find the line that contains -.IT their -so -you can change it to -.IT the . -Now with only three lines in the buffer, it's pretty easy -to keep track of what line the word -.IT their -is on. -But if the buffer contained several hundred lines, -and you'd been making changes, deleting and rearranging 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. -.PP -The way to say ``search for a line -that contains this particular string of characters'' -is to type -.P1 -/\fIstring of characters we want to find\fP/ -.P2 -For example, -the -.ul -ed -command -.P1 -/their/ -.P2 -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: -.P1 -to come to the aid of their party. -.P2 -``Next occurrence'' means that -.ul -ed -starts looking for the string at line -.UL .+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 -.UL $ -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, -.ul -ed -types the error message -.P1 -? -.P2 -Otherwise it prints the line it found. -.PP -You can do both the search for the desired line -.ul -and -a -substitution all at once, like this: -.P1 -/their/s/their/the/p -.P2 -which will yield -.P1 -to come to the aid of the party. -.P2 -There were three parts to that last command: -context search for the desired line, make the substitution, print the line. -.PP -The expression -.UL /their/ -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 -.UL s . -They were used both ways in the examples above. -.PP -Suppose the buffer contains the three familiar lines -.P1 -Now is the time -for all good men -to come to the aid of their party. -.P2 -Then the -.ul -ed -line numbers -.P1 -/Now/+1 -/good/ -/party/\-1 -.P2 -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 -.P1 -/Now/+1s/good/bad/ -.P2 -or -.P1 -/good/s/good/bad/ -.P2 -or -.P1 -/party/\-1s/good/bad/ -.P2 -The choice is dictated only by convenience. -You could print all three lines by, for instance -.P1 -/Now/,/party/p -.P2 -or -.P1 -/Now/,/Now/+2p -.P2 -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 -.P1 -1,$p -.P2 -but not if there were several hundred.) -.PP -The basic rule is: a context search expression is -.ul -the same as -a line number, so it can be used wherever a line number is needed. -.SH -Exercise 6: -.PP -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. -.PP -Try using context searches as line numbers for the -substitute, print and delete commands. -(They can also be used -with -.UL r , -.UL w , -and -.UL a .) -.PP -Try context searching using -.UL ?text? -instead of -.UL /text/ . -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. -.PP -(If you get funny results with any of the characters -.P1 -^ \*. $ [ * \e & -.P2 -read the section on ``Special Characters''.) -.PP -.ul -Ed -provides a shorthand for repeating a context search -for the same string. -For example, -the -.ul -ed -line number -.P1 -/string/ -.P2 -will find the next occurrence of -.UL string . -It often happens that this is not the desired line, -so the search must be repeated. -This can be done by typing merely -.P1 -// -.P2 -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 -.P1 -/string1/s//string2/ -.P2 -which will find the next occurrence of -.UL string1 -and replace it by -.UL string2 . -This can save a lot of typing. -Similarly -.P1 -?? -.P2 -means ``scan backwards for the same expression.'' //GO.SYSIN DD e4 echo e5 sed 's/.//' >e5 <<'//GO.SYSIN DD e5' -.SH -Change and Insert \- ``c'' and ``i'' -.PP -This section discusses the -.ul -change -command -.P1 -c -.P2 -which is used to change -or replace a group of one or more lines, -and the -.ul -insert -command -.P1 -i -.P2 -which is used for inserting a group of one or more lines. -.PP -``Change'', written as -.P1 -c -.P2 -is used to replace a number of lines with different lines, which -are typed in at the terminal. -For example, -to change lines -.UL .+1 -through -.UL $ -to something else, type -.P1 -\&.+1,$c -\&. . . \fItype the lines of text you want here\fP . . . -\*. -.P2 -The lines you type between the -.UL c -command and -the -.UL . -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. -.PP -If only one line is specified in the -.UL c -command, then just -that line is replaced. -(You can type in as many replacement lines as you like.) -Notice -the use of -.UL . -to end the -input \- this works just like the -.UL . -in the append command -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. -.PP -``Insert'' is similar to append \- for instance -.P1 -/string/i -\&. . . \fItype the lines to be inserted here\fP . . . -\*. -.P2 -will insert the given text -.ul -before -the next line that contains ``string''. -The text between -.UL i -and -.UL . -is -.ul -inserted before -the specified line. -If no line number is specified dot is used. -Dot is set to the last line inserted. -.SH -Exercise 7: -.PP -``Change'' is rather like a combination of -delete followed by insert. -Experiment to verify that -.P1 -\fIstart, end\fP d -i -.ul -\&. . . text . . . -\*. -.P2 -is almost the same as -.P1 -\fIstart, end\fP c -.ul -\&. . . text . . . -\*. -.P2 -These are not -.ul -precisely -the same -if line -.UL $ -gets deleted. -Check this out. -What is dot? -.PP -Experiment with -.UL a -and -.UL i , -to see that they are -similar, but not the same. -You will observe that -.P1 -\fIline\(hynumber\fP a -\&. . . \fItext\fP . . . -\*. -.P2 -appends -.ul -after -the given line, while -.P1 -\fIline\(hynumber\fP i -\&. . . \fItext\fP . . . -\*. -.P2 -inserts -.ul -before -it. -Observe that if no line number is given, -.UL i -inserts before line dot, while -.UL a -appends -after line dot. -.SH -Moving text around: the ``m'' command -.PP -The move command -.UL 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 saying: -.P1 -1,3w temp -$r temp -1,3d -.P2 -(Do you see why?) -but you can do it a lot easier with the -.UL m -command: -.P1 -1,3m$ -.P2 -The general case is -.P1 -\fIstart line, end line\fP m \fIafter this line\fP -.P2 -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 -.P1 -First paragraph -\&. . . -end of first paragraph. -Second paragraph -\&. . . -end of second paragraph. -.P2 -you could reverse the two paragraphs like this: -.P1 -/Second/,/end of second/m/First/\-1 -.P2 -Notice the -.UL \-1 : -the moved text goes -.ul -after -the line mentioned. -Dot gets set to the last line moved. -.SH -The global commands ``g'' and ``v'' -.PP -The -.ul -global -command -.UL g -is used to execute one or more -.ul -ed -commands on all those lines in the buffer -that match some specified string. -For example -.P1 -g/peling/p -.P2 -prints all lines that contain -.UL peling . -More usefully, -.P1 -g/peling/s//pelling/gp -.P2 -makes the substitution everywhere on the line, -then prints each corrected line. -Compare this to -.P1 -1,$s/peling/pelling/gp -.P2 -which only prints the last line substituted. -Another subtle difference is that -the -.UL g -command -does not give a -.UL ? -if -.UL peling -is not found -where the -.UL s -command will. -.PP -There may be several commands -(including -.UL a , -.UL c , -.UL i , -.UL r , -.UL w , -but not -.UL g ); -in that case, -every line except the last must end with a backslash -.UL \e : -.P1 -g/xxx/\*.-1s/abc/def/\\ -\&\*.+2s/ghi/jkl/\\ -\&\*.-2,\*.p -.P2 -makes changes in the lines before and after each line -that contains -.UL xxx , -then prints all three lines. -.PP -The -.UL v -command is the same as -.UL g , -except that the commands are executed on every line -that does -.ul -not -match the string following -.UL v : -.P1 -v/ /d -.P2 -deletes every line that does not contain a blank. //GO.SYSIN DD e5 echo e6 sed 's/.//' >e6 <<'//GO.SYSIN DD e6' -.SH -Special Characters -.PP -You may have noticed that things just don't work right when you used -some characters like -\*., -.UL * , -.UL $ , -and others in -context searches and the substitute command. -The reason is rather complex, although the cure is simple. -Basically, -.ul -ed -treats these characters as special, with special meanings. -For instance, -.ul -in a context search or the first string of the substitute command only, -\*. -means ``any character,'' not a period, so -.P1 -/x\*.y/ -.P2 -means ``a line with an -.UL x , -.ul -any character, -and a -.UL y ,'' -.ul -not -just ``a line with an -.UL x , -a period, and a -.UL y .'' -A complete list of the special characters -that can cause trouble is the following: -.P1 -^ \*. $ [ * \e -.P2 -.ul -Warning: -The backslash character -.UL \e -is special to -.ul -ed. -For safety's sake, -avoid it where possible. -If you have to use one of the special characters -in a substitute command, -you can turn off its magic meaning temporarily -by preceding it with the backslash. -Thus -.P1 -s/\e\e\e\*.\e*/backslash dot star/ -.P2 -will change -.UL \e.* -into ``backslash dot star''. -.PP -Here is a hurried synopsis of the other special characters. -First, the circumflex -.UL ^ -signifies -the beginning of a line. -Thus -.P1 -/^string/ -.P2 -finds -.UL string -only if it is at the beginning of a line: -it will find -.P1 -string -.P2 -but not -.P1 -the string... -.P2 -The dollar-sign -.UL $ -is just the opposite of the circumflex; -it means the end of a line: -.P1 -/string$/ -.P2 -will only find an occurrence of -.UL string -that is at the end of some line. -This implies, of course, -that -.P1 -/^string$/ -.P2 -will find only a line that contains just -.UL string , -and -.P1 -/^\*.$/ -.P2 -finds a line containing exactly one character. -.PP -The character -.UL . , -as we mentioned above, -matches anything; -.P1 -/x\*.y/ -.P2 -matches any of -.P1 -x+y -x-y -x y -x\*.y -.P2 -This is useful in conjunction with -.UL * , -which is a repetition character; -.UL a* -is a shorthand for ``any number of -.UL a 's,'' -so -.UL .* -matches any number of anythings. -This is used like this: -.P1 -s/\*.*/stuff/ -.P2 -which changes an entire line, -or -.P1 -s/\*.*,// -.P2 -which deletes all characters in the line up to and -including the last comma. -(Since -.UL .* -finds the longest possible match, -this goes up to the last comma.) -.PP -.UL [ -is used with -.UL ] -to form ``character classes''; -for example, -.P1 -/[0123456789]/ -.P2 -matches any single digit \- -any one of the characters inside the braces -will cause a match. -This can be abbreviated to -.UL [0\-9] . -.PP -Finally, the -.UL & -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 -.P1 -Now is the time -.P2 -and you wanted to put parentheses around it. -You could just retype the line, but -this is tedious. -Or you could say -.P1 -s/^/(/ -s/$/)/ -.P2 -using your knowledge of -.UL ^ -and -.UL $ . -But the easiest way uses the -.UL & : -.P1 -s/\*.*/(&)/ -.P2 -This says ``match the whole line, and replace it -by itself surrounded by parentheses.'' -The -.UL & -can be used several times in a line; -consider -using -.P1 -s/\*.*/&? &!!/ -.P2 -to produce -.P1 -Now is the time? Now is the time!! -.P2 -.PP -You don't have to match the whole line, of course: -if the buffer contains -.P1 -the end of the world -.P2 -you could type -.P1 -/world/s//& is at hand/ -.P2 -to produce -.P1 -the end of the world is at hand -.P2 -Observe this expression carefully, -for it illustrates how to take advantage of -.ul -ed -to save typing. -The string -.UL /world/ -found the desired line; -the shorthand -.UL // -found the same -word in the line; -and the -.UL & -saves you from typing it again. -.PP -The -.UL & -is a special character only within -the replacement text of a substitute command, -and has no special meaning elsewhere. -You can turn off the special meaning of -.UL & -by preceding it with a -.UL \e : -.P1 -s/ampersand/\e&/ -.P2 -will convert the word ``ampersand'' into the literal symbol -.UL & -in the current line. //GO.SYSIN DD e6 echo e7 sed 's/.//' >e7 <<'//GO.SYSIN DD e7' -.sp 2 -.SH -Summary of Commands and Line Numbers -.PP -The general form of -.ul -ed -commands is the command name, -perhaps preceded by one or two line numbers, and, -in the case of -.UL e , -.UL r , -and -.UL w , -followed by a file name. -Only one command is allowed per line, -but a -.UL p -command may follow any other command -(except for -.UL e , -.UL r , -.UL w -and -.UL q ). -.LP -.UL 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. -.LP -.UL c : -Change the specified lines to the new text which follows. -The new lines are terminated by a -\*., -as with -.UL a . -If no lines are specified, -replace line dot. -Dot is set to last line changed. -.LP -.UL d : -Delete the lines specified. -If none are specified, delete line dot. -Dot is set to the first undeleted line, -unless -.UL $ -is deleted, -in which case dot is set to -.UL $ . -.LP -.UL e : -Edit new file. -Any previous -contents of the buffer are thrown away, -so issue a -.UL w -beforehand. -.LP -.UL f : -Print remembered filename. -If a name follows -.UL f -the remembered name will be set to it. -.LP -.UL g : -The command -.P1 -g/\(hy\(hy\(hy/commands -.P2 -will execute the commands on those lines that contain -.UL --- , -which can be any context search expression. -.LP -.UL i : -Insert lines before specified line (or dot) -until a -\*. -is typed on a new line. -Dot is set to last line inserted. -.LP -.UL m : -Move lines specified to after the line -named after -.UL m . -Dot is set to the last line moved. -.LP -.UL p : -Print specified lines. -If none specified, print -line dot. -A single line number is equivalent to -.IT line-number -.UL p . -A single return prints -.UL .+1 , -the next line. -.LP -.UL q : -Quit -.IT ed . -Wipes out all text in buffer -if you give it twice in a row without first giving a -.UL w -command. -.LP -.UL r : -Read a file into buffer (at end unless specified -elsewhere.) Dot set to last line read. -.LP -.UL s : -The command -.P1 -s/string1/string2/ -.P2 -substitutes the characters -.UL string1 -into -.UL string2 -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. -.UL s -changes only the first occurrence of -.UL string1 -on a line; -to change all of them, type a -.UL g -after the final slash. -.LP -.UL v : -The command -.P1 -v/\(hy\(hy\(hy/commands -.P2 -executes -.UL commands -on those lines that -.ul -do not -contain -.UL --- . -.LP -.UL w : -Write out buffer onto a file. -Dot is not changed. -.LP -.UL .= : -Print value of dot. -.UL = "" ( -by itself prints the value of -.UL $ .) -.LP -.UL ! : -The line -.P1 -!command\(hyline -.P2 -causes -.UL command-line -to be executed as a -.UC UNIX -command. -.LP -.UL /-----/ : -Context search. -Search for next line which contains -this string of characters. -Print it. -Dot is set to the line where string -was found. -Search starts at -.UL .+1 , -wraps around from -.UL $ -to -1, -and continues to dot, if necessary. -.LP -.UL ?-----? : -Context search in reverse direction. -Start search -at -.UL .\-1 , -scan to 1, -wrap around to -.UL $ . //GO.SYSIN DD e7