UNIX Editors I
This handout covers the first of the two standard UNIX editors, ed. It does not attempt to address strange and mystical editors like emacs, as they may not be present on all systems. In addition, this handout only attempts to address the most common uses of ed. It does not delve into the more esoteric features like editing multiple files in the same time.
In this series we will progress in historical order, starting with the ed editor. Next we will address the extension of the ed editor ex, and finally consider the visual version of ex, vi.
Before we begin, it is important to understand why a UNIX programmer should know these editing tools when more elegant editors like emacs exist. There are five good reasons to become familiar with these editors:
1. Some of the commands from the early editors like ed can be used with later, more sophisticated editors. If you should forget how to use one of the screen editors to perform some task, you can use the ed command sequence.
2. String searches use the same constructs in the majority of the UNIX editors. In addition, global commands may be difficult to perform in some editors, but are easy in the early editors like ed and ex.
3. The syntax you learn with ed is also used in other UNIX tools like grep and diff. Learning ed will enable you to use these other tools with less difficulty.
4. After learning the tools available in ed, other powerful file editing tools like sed are easy and natural to use to edit whole files.
5. If you are using a hard copy terminal, or if your stty file becomes corrupted and you don't have access to a screen editor you can still perform edits using line editors like ed and ex.
6. It is often easier to direct someone to use a line editor like ed, rather than have them start a screen editor like vi. The ed or ex editor is often the choice of telephone tech support because it is less complex to walk users through its use.
History of ed
The early versions of the ed editor, also known as the "standard Unix editor," were written by Ken Thompson. It is descended from the QED editor which was written by Butler Lampson and Peter Deutsch at Berkeley, in the middle 1960s. Before he wrote ed, Thompson wrote a version of QED for the Multics project. Dennis Ritchie also worked on that early, Bell Labs version, of QED. However, Thompson wanted a simpler editor so he built the first version of ed. In its evolution, many other people have worked on ed, and it has become a more complex and more powerful editor. Nonetheless, ed has retained much of the original flavor and functionality given it by Thompson in the late '60s.
One of the interesting things about both of the standard Unix editors, (ed and ex/vi) is that they are "line editors" rather than page editors or document editors. This sometimes takes a little getting used to, as most of us are more familiar with the modern, full document, or word processors. To understand ed we need to consider the time at which ed was developed, and technology available at the time.
Remember that ed was developed back in the late 1960s and the "state-of-the-art" input device back then was the teletype, typified by the ASR-33 which first saw the light of day in 1968. This absolutely classic, all-around I/O Device was able to print a blazing, (for its time), 10 characters or 80 bits per second (upper case and symbols only), generating input at the same speed from its keyboard. It also had a built in punched paper tape reader, and could punch paper tape for output and off-line storage. Some models of this unit could even start and stop the paper tape reader or the paper tape punch on command from a host computer which is why it was given the "ASR" (Automatic Send & Receive) designation in it's name.
With a very slow I/O device long involved command names are very inefficient. That is why most of the ed commands are only one or two characters long. In addition to being slow the teletype or ASR 33 was a hard copy device. That meant that the user could look back on the paper and see what they had typed, unlike a monitor where you can only see 24 lines. For that reason there was no need to "refresh the screen" because all that would do would be print a lot of lines, pushing the paper up at 10 characters per second which would take a lot of time. The ed editor was designed to work on a single line of the input file at a time. Hence the appellation line editor.
As ed grew and developed over time, he acquired the ability to perform edits on a number of lines at the same time. He has also acquired new, additional, features that made him more powerful and more useful.
All the descendents of ed are forms of a line editor. A line editor is one which enables the user to work with a single line of text at a time. Once ed has at least one line of text in the working buffer, there is always a current line that is the default target for any edit.
When you open a file in ed, or when you start typing a new file, ed creates a working buffer, called the editing buffer. This buffer holds the information in memory. Any changes you make will not be applied to the disk file until you execute a "write to disk" command. This means you can back out of changes easily, but it also means that you can lose a whole session's work if you forget to write the contents of the editing buffer back to disk before you quit ed. Fortunately, if you allow it, ed will remind you to save the contents of the editing buffer before you exit.
1.1 Starting ed
It is simple to invoke the ed editor. All you need to do is type either:
ed or ed filename at the system prompt to invoke the ed editor.
Figure 1 on the opposing page, shows how to invoke the ed editor without specifying a file name.
Figure 2 shows how to start ed and give it a file to edit. Note: ed will tell you how many characters or bytes are in an existing file as it reads them into the editing buffer.
Please note: For purposes of this text, the standard C shell prompt % is used to show the operating system prompt. When you see a %, that indicates a command to be entered on the command line.
In both examples, the first command clear simply clears the screen before ed is started. This makes the interaction with ed less cluttered and helps identify the ed command. I will eliminate the clear command from subsequent lines to reduce the clutter. However, I recommend you always issue the clear command before you start ed.
1.2 The two modes of ed
The UNIX editors work in one of two modes:
a. command mode
b. text entry mode
Many new users find it somewhat confusing determining which mode ed is in (as well as switching back and forth between modes). If ed is in text entry mode, then all of the ed commands you enter will be taken as text input and inserted into the document you are editing. On the other hand, if you are in command mode, ed will try to interpret anything you type as if it were commands, (and possibility become very confused). One of the most common problems new users have with this is being in text entry mode and trying to use ed commands. Those commands will appear one after the other, but as ed is in text entry mode, they will not be executed. This can be both confusing and frustrating.
To help you remember which mode you are in, ed has a command that asks it to tell you when it is in command mode. Figure 3 shows the use of the P ( or give me a special Prompt) command. Please note that like the majority of other UNIX utilities, ed is case sensitive. This command is the upper case P. After you enter a P, ed will present an asterisk * as a prompt when it is in command mode. When ed is in text entry mode there will be no prompt. If you want to turn this option back off, simply type another P command. (Commands that are turned on and off by successive entries of the same key are called "toggle" commands. Several of the ed commands toggle.)
1.3 Error messages in ed
In accordance with the terse nature of early UNIX editors, ed is very brief when identifying input errors. Figure 4 shows the error message generated by ed. As it is less than helpful, Figure 5 shows how to invoke the ed help message description tool. Although ed is not terribly verbose, it does help in some cases, especially when you already know what you have done wrong. In this case, the p command told ed to print the current line in the editing buffer to the screen. However, there is no line in the editing buffer available to print, so ed recognizes it as an error. To show that it has a problem with a command, ed prints a ?.
Finally, Figure 6 shows how to turn on the verbose message option for your current session with ed. This option will remain on for your whole editing session.
Note: The text lines shown in italics are comments on the session and not part of the actual editing session.
1.4 Leaving the ed editor
When you are ready to end your editing session all you need to do is enter the q command (for quit) at the command prompt.
If you have not saved the editing buffer to disk since your last change, ed will prompt you to do so by issuing an error message. If you enter a second q ed will do as you asked, exit, and not save your work. If you make the double q your standard exit from ed you will, at some time, exit without having saved your work and have the chance to save the text in the editing buffer.
Figure 7 shows us adding some text to a file, and then trying to exit without saving. It shows how ed will provide an error message prompting us to save (write) the contents of the buffer to the file. In this example we exited without saving our work.
In this same light, there is a way to leave the ed editor without any chance of saving your work. If you enter the Q command, ed will exit and not check the status of the editing buffer to see if the most recent changes have been saved. This is the most dangerous way to exit from ed. (Remember, back in the beginning I told you you would have to allow ed to help you remember to save the contents of the editing buffer...this shows you how you can prevent ed from helping you...this is generally considered to be a Bad Thing by the forces for good in the community.)
In Figure 8, we also added some text, but then issued the absolute quit command, Q. Notice that the next thing we see is the command line prompt, showing that we have exited form ed without saving our work.
Figure 9 shows the preferred way to respond to the error on exit message. Save the contents of the editing buffer to a file, and then reissue the q command to ask ed to exit to the shell.
Had we written our data from the buffer to the disk first, and then issued a quit command, ed would have simply exited to the command line with no message at all. Figure 10 shows that process.
1.5 Displaying the lines in a buffer.
Each time you access a line of the buffer, ed shows you the contents of that line. However, it is often handy to be able to display all or a subset of the lines in a file so you can see what the file looks like.
There are two ways to show a set of lines in ed, either with or without line numbers. Using the l, or list, command will show you the current line. You can also specify the address of a particular line and see that line. Finally, you can specify a range of lines and see all of those lines. Figure 11 shows all of these variants. (I now will assume that you realize that you must type a <return> after each command or input line and will no longer show those <return>s.)
Sometimes it is handy to have ed tell us the line numbers. For example, if we are writing a program or script and the interpreter tells us that there is an error in line 46, it might be handy to see not only line 46, but the lines that surround 46. As with the list command, the n, or number command by itself will display the current or active line preceded by its line number. You can specify a single line number, or a range of line numbers and see that line or range. Figure 12 shows how these options work.
This is a good time to introduce you to a couple of short cuts in addressing. As you have seen in the two examples of showing buffer contents, you can specify a first line number address and a last line number address and see all of the lines between those two, including the named lines.
There are times when you may want to see all of the lines in the buffer. Let's pretend that there are 19 lines in the buffer. You could specify 1,19l to see all 19 lines. However, suppose you don't know how many lines there are in the buffer. There is a magic address, $, that says "the last line in the buffer". So rather than typing 1,19l we can simply type 1,$l saving one whole keystroke. By the same token, we could type 10,$l and see all the lines from 10 to the last one in the file.
If you want to see all of the lines in the file, there is a second, even shorter cut you can use. Rather than typing 1,$n, you can simply type ,n (comma n). In this case ed will assume you mean 1,$n. That is pretty handy if your file is relatively short and you want to manipulate all of the lines. You can use these shortcuts with any command that takes addresses, or line numbers, as part of the command. So, for example, if you wanted to delete all of the lines in a file, you could simply type ,d. Short, sweet, quick, efficient, all of the qualities we want in an editor.
1.6 Moving about in a file with ed
The easiest way to move about in a file is to simply enter the line number you wish to "go to". Figure 13 shows how to enter 3 lines of text, and then transfer control to line 1 and then to line 3. Note the use of the n command to display the line number and the text of the line after it becomes the current line.
Figure 14 shows one of the ways to perform relative addressing in ed. The editor is started, text is entered into the editing buffer, and then the text entry (append) mode is ended by the period (.). At this point, the third line, (the most recent line entered) is the current line. Next the command -2 is entered. This command is the same as the
.-2 command (. standing for "here" or the current line). Next the n command is used to show which line is now the current line. Please don't confuse the period used to end the append session with the period used to represent here or the current line. It is obvious to the most casual observer that the two symbols are very different. Yea, right, sure! ;-)
1.7 Adding text to a file
Figure 15 shows how to insert text into a new file. (You have seen this example before, now we will discuss the actual mechanism). As you will remember, we cannot insert text into a new file because insert inserts text before the current (or named) line, and we have no lines yet. Therefore we must append our text to the first line of the file (line zero). After we have appended a line, we can then use the insert command to add additional text to the body of the file. The (Please note, from now on, the examples assume you have typed both the H and the P commands at some previous point in the editing session.
1.8 Searching in a file
Figure 16 shows the two common ed search tools. The first is the forward search which starts at the current line and searches forward through the rest of the file to find the first occurrence of the string specified between the slashes. In this example, the search stops when it finds the first occurrence of the word "UNIX". The second search shown works upwards, or backward (toward the beginning of the file) from the current line. It stops when it finds the first occurrence of the string specified between the question marks. Please note: The editing buffer seems to be circular when searching with these tools. You can visualize a circular buffer as if it has its contents on the outside of a cylinder. When you reach the last line of the file, the next line "down" is the first line of the file. By the same token, if you move to the line "above" the first line of the file, you reach the last line of the file.
Figure 17 shows the global parameter. When the g (or global) command precedes the search pattern, each line in the file is checked for the occurrence of the pattern specified. In this case, the pattern is a lower case l (ell). Each line that contains this pattern will be reported (printed on the screen). Please note that the search pattern is often a Regular Expression.
1.9 Deleting lines from a file
Figure 18 shows how to remove lines from a file. The format of the delete command is #,#d where the line number or numbers are optional. If there are no line numbers given, the delete command will delete the current line. The delete command can be preceded by a single line number to delete a single line. Remember, the undo command (u) will undo the most recent delete (if you remember to do it before you execute another undoable command.)
1.10 Finding (or changing) the name of the current file
In Figure 19 we see how to determine the name of the file associated with the buffer we are currently working with. (Remember, the contents of the file will not be altered until we issue a w write command.) The f command by itself prints the name of the file associated with the current editing buffer. If we include the name of a file, then that file becomes associated with the the current buffer. Remember, the contents of the editing buffer will not be saved in that file until you issue the write w command.
1.11 Combining two lines together
Figure 20 shows the join command j. This command will remove the carriage return, line feed (newline) at the end of the first line, joining the second line with the first. This command takes as parameters, two contiguous lines. (That means you can join lines numbered 4 and 5, but not lines numbered 4 and 11.) Please note in the example, that the two lines are joined, but as there were no spaces either at the end of the first line nor at the beginning of the second line, there is no space between the words "time" and "For". You would need to go back into this file and fix that mistake after the join command finished.
1.12 Moving lines around in the buffer
This editor also gives you the opportunity to move lines from one place to another in the buffer. Figure 21 shows how to accomplish a simple move. Please note that the line(s) to be moved are moved to the line following the line listed as the target.
1.13 Copying lines in the buffer
While the move command (m) gives us the functional equivalent to the standard cut and paste function, the copy command t (stands for transfer, perhaps<?>) allows you to copy and paste. The format of this command is #,#t# where the line number pair give ed the range of lines you wish to copy, and the last line number gives the location to copy to. As with move, the text will appear in the buffer following the line number listed. Figure 22 demonstrates a simple move.
1.14 Substitution in ed
This editor also allows specific search and replacement. The s command provides that capability. The format of the command is #,#s/target/new value/n where n is a number indicating the occurrence on the line of the target to be replaced or substituted. If you do not provide a value for n, the substitute command will replace the first occurrence of the target string. Should you want ed to replace all the occurrences of the target string with the new value, use a "g" for global, in place of the n. Figure 23 shows this command and the results of a simple substitution.
Remember, substitution is your very best friend!
1.15 Other ed commands
There are many more editing commands, as listed in the "Table of Useful ed Commands" following the next set of examples. After you master the commands we have discussed here, you should play with, and learn, the rest of the ed commands. You will find that a complete grasp of the intricies of ed will help you with all of your other editing tasks. Besides, ed is a pretty cool tool!
A table of useful ed commands
! This command will act like a shell escape character and allow the subsequent key strokes to be passed to the UNIX shell and executed. In most cases control returns to ed after the execution of the command.
a Allows you to leave command mode and append text after the current line.
c The change command allows you to alter a range of text. The generic format of the command is [#,#]c where #,# is a range of lines you wish to replace with text you will type. This command first deletes the existing text over the range specified, and then puts you into insert mode to type new text to replace that which has been deleted.
d This command allows you to delete one or more lines, the generic format of the command is [#,#]d where #,# is a range of lines to be deleted. The line after the last line deleted becomes the current line.
e Reads the previously saved version of the current file into the editing buffer. If a file name is specified, then ed loads the most recent version of that file into the editing buffer, overwriting the current contents.
f By itself, f displays the current filename, if you give f a file name, then you give a new name to the contents of the editing buffer. The syntax for this command is f or f filename to set a new filename.
g is the global option. If g precede a command, then the entire buffer is searched for all first occurrences of the pattern in each line, if the g follows the command, then the whole line is searched, and ed does not stop with the first occurrence. It is possible to attach a command-list to this command to be executed each time the pattern is matched. The normal syntax of this command is [#,#]g/RE/command-list. The commands in the command list must be separated by protected new lines (\<enter>). If the g both precedes and follows a command, then the complete file is searched.
G This command is the same as the g command, except it can have only 1 command following it rather than a command list.
h Displays the most recent error message.
H Displays, (or redisplays) the most recent error message and turns on the automatic, verbose error message display for the current editing session. This command is a toggle, if you enter a second H, it will turn verbose error display off. The default for this option is off.
i This command allows you to insert text before the current line. If you precedes the command with a number, the text will be opened for insertion before the line specified.
A table of useful ed commands (cont.)
j The j command allows you to remove the carriage return between any two lines, joining them into one line. The format of that command is: [#,#]j where # and # are two contiguous lines to be joined. If you do not give join two line numbers, the command will fail, but no error message will be given.
k This command will set a marker in the text so you can find a particular line later. The format of this command is [#]kx where x is one of the letters from the range [a-z]. If no line number (#) is supplied, the current line is marked. To transfer control back to a line so marked, use the 'x command. (that is tick-mark x)
l List either the entire contents of the buffer, or in the form [#,#]l, list the range of lines specified. In the second form, the last line listed becomes the current line.
m The move command moves a specified range of text to a new location in the editing buffer. The correct form for the move command is : [#,#]m# where the #,# pair are the lines to be moved, and the # following the command shows where the lines will be moved. The line(s) will be moved to the line following the target line.
n The generic form of the number command displays some range of numbers ([#,#]n) on the screen, preceding each line with the line number and the tab character. At the end of the command, the last line displayed becomes the current line.
p This command prints either the current line or the lines specified by the number range that precedes the command ([#,#]p), then the lines listed are printed (shown on the screen) and the last line printed becomes the current line.
P This toggle turns on or off the command mode prompt. (The default for this toggle is off.)
q q lets you quit an ed session. If you have not saved the contents of the editing buffer, ed will give you the ? error message. If you issue another q command, ed will exit and not save the contents of the editing buffer.
Q If you want to end an ed session without verifying that the contents of the editing buffer have been saved, use the Q command. This is a dangerous command.
r The format of this command is: [#,#}r filename, where the contents of the file specified by filename is copied into the file at the location following the line(s) specified. If no filename is specified, the current file is used, and if there is no current file, an error message is generated.
A table of useful ed commands (cont.)
s The substitute command searches the current line for the specified text (stext). If ed finds the search text, it replaces it with the replacement text (rtext). The form of the command is [#,#]s/stext/rtext/n. If the line numbers are omitted, substitute works on the first occurrence it finds. This command can take an n suffix, if used, the nth occurrence of the stext will be replaced. The global options are frequently used with this command.
t [#,#]t# is the format of the copy command (to remember it, you are copying from a range to a line number?). This command copies the line(s) of text specified and inserts them after the line number specified as the target.
u The undo command will help you recover from an error. You can undo the actions of the most recent a, c, d, i, j, m, r, s, t, u, v ,G, or V command. You must use the undo command before you issue another command in the list above, for the undo to work. If you leave the ed editor and return, you cannot undo a change. You cannot undo a change that has been written to disk. Please note, you can undo the results of an undo command as well!
v This command is the opposite of the g command. Where g finds all occurrences of the pattern listed, v finds all lines that do not match the pattern. If a command-list is supplied, that command line is executed for each line that does not match the specified pattern. The proper syntax is [#,#]v/RE/command-list.
V This command is the opposite of the G command. (See the discussion of v).
^V Using this command allows you to enter non-displaying character ASCII code into the buffer. For example the string ^V^G imbeds the ASCII code for ^G (beep) into the text. Useful for some specialized ASCII (or "escape") sequences. (^ represents the CTRL or control key, so ^V means Control-V.)
w If no file name is specified, this command writes the contents of the editing buffer to the disk file that was opened (or edited, or read) to initially load the editing buffer. This command will allow a subset of the editing buffer to be saved, that format is [#,#]w filename. If no line numbers are specified, the whole file is written. If a file name is specified as an argument, then that portion of the editing buffer specified is written to the disk and saved under the filename.
W This command is similar to the w except that it appends to an existing file rather than writing over the contents.
/RE/ This is used to search forward through the file for the first occurrence of the pattern enclosed in slashes. In this case, that is a regular expression.
?RE? This is used, like the slashes, but starts a search backward Please note, for purposes of these searches, the buffer is circular.
A table of some Regular Expressions
Regular Expression Matches
/A/ The first upper case A in the line (Note, A does not have to be the first character in the line to match this RE).
. Matches any single character.
* Matches zero or more consecutive occurrences of the single character preceding it.
$ Represents the end of the line.
^ Represents the beginning of the line.
\ An "escape" or protection character that prevents the shell from seeing the very next character following the backslash.
 Delineates a set of zero or more characters as the search string, where any one of the characters in the braces satisfies the match criteria.
& This metacharacter represents the value of the string to be matched it is used in substitution commands.
A table of Pseudo-Addresses for ed
(Note, do not confuse these with Regular Expression Metacharacters.)
$ This is the pseudo address that represents the last line in the buffer.
, This represents the address range 1,$ (first line through the end of the buffer.)
; This represents the address range .,$ (current line through the end of the buffer.)
. This is the pseudo address that represents the current line. The command .p would print the current line.
1 Any digit will make that line number the current line and print it, so the command 1 (the number one) is the same as 1p, it makes line 1 the current line and prints that line. In many books, a line number is shown as the octothorp #.