This manual is for GNU ed (version 0.4, 15 January 2007).
GNU ed is an 8-bit clean, more or less POSIX-compliant implementation of the standard Unix line editor. These days, full-screen editors have rendered ed mostly of historical interest. Nonetheless, it appeals to a handful of aging programmers who still believe that “Small is Beautiful”.
Copyright © 1993, 2006, 2007 Free Software Foundation, Inc.
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
ed is a line-oriented text editor. It is used to create, display, modify and otherwise manipulate text files. red is a restricted ed: it can only edit files in the current directory and cannot execute shell commands.
If invoked with a file argument, then a copy of file is read into the editor's buffer. Changes are made to this copy and not directly to file itself. Upon quitting ed, any changes not explicitly saved with a `w' command are lost.
Editing is done in two distinct modes: command and input. When first invoked, ed is in command mode. In this mode commands are read from the standard input and executed to manipulate the contents of the editor buffer. A typical command might look like:
,s/old/new/g
which replaces all occurences of the string old with new.
When an input command, such as `a' (append), `i' (insert) or `c' (change), is given, ed enters input mode. This is the primary means of adding text to a file. In this mode, no commands are available; instead, the standard input is written directly to the editor buffer. A line consists of the text up to and including a <newline> character. Input mode is terminated by entering a single period (`.') on a line.
All ed commands operate on whole lines or ranges of lines; e.g., the `d' command deletes lines; the `m' command moves lines, and so on. It is possible to modify only a portion of a line by means of replacement, as in the example above. However even here, the `s' command is applied to whole lines at a time.
In general, ed commands consist of zero or more line addresses, followed by a single character command and possibly additional parameters; i.e., commands have the structure:
[address [,address]]command[parameters]
The addresses indicate the line or range of lines to be affected by the command. If fewer addresses are given than the command accepts, then default addresses are supplied.
ed was created, along with the Unix operating system, by Ken Thompson and Dennis Ritchie. It is the refinement of its more complex, programmable predecessor, QED, to which Thompson and Ritchie had already added pattern matching capabilities (see Regular Expressions).
For the purposes of this tutorial, a working knowledge of the Unix shell sh (see Bash) and the Unix file system is recommended, since ed is designed to interact closely with them.
The principal difference between line editors and display editors is that display editors provide instant feedback to user commands, whereas line editors require sometimes lengthy input before any effects are seen. The advantage of instant feedback, of course, is that if a mistake is made, it can be corrected immediately, before more damage is done. Editing in ed requires more strategy and forethought; but if you are up to the task, it can be quite efficient.
Much of the ed command syntax is shared with other Unix utilities.
As with the shell, <RETURN> (the carriage-return key) enters a line of input. So when we speak of “entering” a command or some text in ed, <RETURN> is implied at the end of each line. Prior to typing <RETURN>, corrections to the line may be made by typing either <BACKSPACE> (sometimes labeled <DELETE> or <DEL>) to erase characters backwards, or <CONTROL>-u (i.e., hold the CONTROL key and type u) to erase the whole line.
When ed first opens, it expects to be told what to do but doesn't prompt us like the shell. So let's begin by telling ed to do so with the <P> (prompt) command:
$ ed P *
By default, ed uses asterisk (`*') as command prompt to avoid confusion with the shell command prompt (`$').
We can run Unix shell (sh) commands from inside ed by prefixing them with <!> (exclamation mark, aka “bang”). For example:
*!date Mon Jun 26 10:08:41 PDT 2006 ! *!for s in hello world; do echo $s; done hello world ! *
So far, this is no different from running commands in the Unix shell. But let's say we want to edit the output of a command, or save it to a file. First we must capture the command output to a temporary location called a buffer where ed can access it. This is done with ed's <r> command (mnemonic: read):
*r !cal 143 *
Here ed is telling us that it has just read 139 characters into the editor buffer - i.e., the output of the cal command, which prints a simple ASCII calendar. To display the buffer contents we issue the <p> (print) command (not to be confused with the prompt command, which is uppercase!). To indicate the range of lines in the buffer that should be printed, we prefix the command with <,> (comma) which is shorthand for “the whole buffer”:
*,p September 2006 Mo Tu We Th Fr Sa Su 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 *
Now let's write the buffer contents to a file named junk
with the
<w> (write) command. Again, we use the <,> prefix to
indicate that it's the whole buffer we want:
*,w junk 143 *
Need we say? It's good practice to frequently write the buffer contents, since unwritten changes to the buffer will be lost when we exit ed.
The sample sessions below illustrate some basic concepts of line editing with ed. We begin by creating a file, `sonnet', with some help from Shakespeare. As with the shell, all input to ed must be followed by a <newline> character. Comments begin with a `#'.
$ ed # The `a' command is for appending text to the editor buffer. a No more be grieved at that which thou hast done. Roses have thorns, and filvers foutians mud. Clouds and eclipses stain both moon and sun, And loathsome canker lives in sweetest bud. . # Entering a single period on a line returns ed to command mode. # Now write the buffer to the file `sonnet' and quit: w sonnet 183 # ed reports the number of characters written. q $ ls -l total 2 -rw-rw-r-- 1 alm 183 Nov 10 01:16 sonnet $
In the next example, some typos are corrected in the file `sonnet'.
$ ed sonnet 183 # Begin by printing the buffer to the terminal with the `p' command. # The `,' means ``all lines.'' ,p No more be grieved at that which thou hast done. Roses have thorns, and filvers foutians mud. Clouds and eclipses stain both moon and sun, And loathsome canker lives in sweetest bud. # Select line 2 for editing. 2 Roses have thorns, and filvers foutians mud. # Use the substitute command, `s', to replace `filvers' with `silver', # and print the result. s/filvers/silver/p Roses have thorns, and silver foutians mud. # And correct the spelling of `fountains'. s/utia/untai/p Roses have thorns, and silver fountains mud. w sonnet 183 q $
Since ed is line-oriented, we have to tell it which line, or range of lines we want to edit. In the above example, we do this by specifying the line's number, or sequence in the buffer. Alternatively, we could have specified a unique string in the line, e.g., `/filvers/', where the `/'s delimit the string in question. Subsequent commands affect only the selected line, a.k.a. the current line. Portions of that line are then replaced with the substitute command, whose syntax is `s/old/new/'.
Although ed accepts only one command per line, the print command `p' is an exception, and may be appended to the end of most commands.
In the next example, a title is added to our sonnet.
$ ed sonnet 183 a Sonnet #50 . ,p No more be grieved at that which thou hast done. Roses have thorns, and silver fountains mud. Clouds and eclipses stain both moon and sun, And loathsome canker lives in sweetest bud. Sonnet #50 # The title got appended to the end; we should have used `0a' # to append ``before the first line.'' # Move the title to its proper place. 5m0p Sonnet #50 # The title is now the first line, and the current line has been # set to this line as well. ,p Sonnet #50 No more be grieved at that which thou hast done. Roses have thorns, and silver fountains mud. Clouds and eclipses stain both moon and sun, And loathsome canker lives in sweetest bud. wq sonnet 195 $
When ed opens a file, the current line is initially set to the last line of that file. Similarly, the move command `m' sets the current line to the last line moved.
In summary:
Structurally, Related programs or routines are vi (1), sed (1), regex (3), sh (1). Relevant documents are:
Unix User's Manual Supplementary Documents: 12 — 13
B. W. Kernighan and P. J. Plauger: “Software Tools in Pascal”, Addison-Wesley, 1981.
The format for running ed is:
ed [options] [file] red [options] [file]
file specifies the name of a file to read. If file is prefixed with a bang (!), then it is interpreted as a shell command. In this case, what is read is the standard output of file executed via sh (1). To read a file whose name begins with a bang, prefix the name with a backslash (\). The default filename is set to file only if it is not prefixed with a bang.
ed supports the following options:
--help
-h
--version
-V
--loose-exit-status
-l
--prompt=
string-p
string--quiet
--silent
-s
--traditional
-G
--verbose
-v
An address represents the number of a line in the buffer. ed maintains a current address which is typically supplied to commands as the default address when none is specified. When a file is first read, the current address is set to the last line of the file. In general, the current address is set to the last line affected by a command.
A line address is constructed from one of the bases in the list below, optionally followed by a numeric offset. The offset may include any combination of digits, operators (i.e., `+' and `-') and whitespace. Addresses are read from left to right, and their values may be absolute or relative to the current address.
One exception to the rule that addresses represent line numbers is the address `0' (zero). This means “before the first line,” and is valid wherever it makes sense.
An address range is two addresses separated either by a comma or semicolon. The value of the first address in a range cannot exceed the value of the the second. If only one address is given in a range, then the second address is set to the given address. If an n-tuple of addresses is given where n > 2, then the corresponding range is determined by the last two addresses in the n-tuple. If only one address is expected, then the last address is used.
Each address in a comma-delimited range is interpreted relative to the current address. In a semicolon-delimited range, the first address is used to set the current address, and the second address is interpreted relative to the first.
The following address symbols are recognized.
.
$
+
-
+
n-
n,
;
/
re/
?
re?
'x
Regular expressions are patterns used in selecting text. For example, the ed command
g/string/
prints all lines containing string. Regular expressions are also used by the `s' command for selecting old text to be replaced with new text.
In addition to a specifying string literals, regular expressions can represent classes of strings. Strings thus represented are said to be matched by the corresponding regular expression. If it is possible for a regular expression to match several strings in a line, then the left-most longest match is the one selected.
The following symbols are used in constructing regular expressions:
\
c.
[
char-class]
[:alnum:] [:cntrl:] [:lower:] [:space:] [:alpha:] [:digit:] [:print:] [:upper:] [:blank:] [:graph:] [:punct:] [:xdigit:]
If `-' appears as the first or last character of char-class, then it matches itself. All other characters in char-class match themselves.
Patterns in char-class of the form:
[.col-elm.] [=col-elm=]
where col-elm is a collating element are interpreted
according to locale (5)
. See
regex (3)
for an explanation of these constructs.
[^
char-class]
^
$
\(
re\)
*
\{
n,
m\}
\{
n,\}
\{
n\}
\<
\>
The following extended operators are preceded by a backslash `\' to distinguish them from traditional ed syntax.
\`
\'
\?
\+
\b
\B
\w
\W
All ed commands are single characters, though some require additonal parameters. If a command's parameters extend over several lines, then each line except for the last must be terminated with a backslash (`\').
In general, at most one command is allowed per line. However, most commands accept a print suffix, which is any of `p' (print), `l' (list), or `n' (enumerate), to print the last line affected by the command.
An interrupt (typically <Control-C>) has the effect of aborting the current command and returning the editor to command mode.
ed recognizes the following commands. The commands are shown together with the default address or address range supplied if none is specified (in parenthesis).
(.)a
(.,.)c
(.,.)d
e
filee !
commandE
filef
file(1,$)g /
re/
command-listAt least the first command of command-list must appear on the same
line as the `g' command. All lines of a multi-line
command-list except the last line must be terminated with a
backslash (`\'). Any commands are allowed, except for `g',
`G', `v', and `V'. By default, a newline alone in
command-list is equivalent to a `p' command. If ed
is invoked with the command-line option `-G', then a newline in
command-list is equivalent to a `.+1p' command.
(1,$)G /
re/
The format of command-list is the same as that of the `g'
command. A newline alone acts as a null command list. A single `&'
repeats the last non-null command list.
H
h
(.)i
(.,.+1)j
(.)kx
(.,.)l
(.,.)m(.)
(.,.)n
(.,.)p
P
q
Q
q
command, except that unwritten changes are discarded without warning.
($)r
file($)r !
command(.,.)s /
re/
replacement/
(.,.)s /
re/
replacement/g
(.,.)s /
re/
replacement/
nre and replacement may be delimited by any character other than <space> and <newline> (see the `s' command below). If one or two of the last delimiters is omitted, then the last line affected is printed as if the print suffix `p' were specified.
An unescaped `&' in replacement is replaced by the currently
matched text. The character sequence `\m' where m is a
number in the range [1,9], is replaced by the mth backreference
expression of the matched text. If replacement consists of a
single `%', then replacement from the last substitution is
used. Newlines may be embedded in replacement if they are escaped
with a backslash (`\').
(.,.)s
(.,.)t(.)
u
(1,$)v /
re/
command-list(1,$)V /
re/
(1,$)w
file(1,$)w !
command(1,$)wq
file(1,$)W
file(.)x
(.,.)y
(.+1)z
n!
command(.,.)#
($)=
(.+1)<newline>
If the terminal hangs up, ed attempts to write the buffer to file ed.hup.
ed processes file arguments for backslash escapes, i.e., in a filename, any characters preceded by a backslash (`\') are interpreted literally.
If a text (non-binary) file is not terminated by a newline character, then ed appends one on reading/writing it. In the case of a binary file, ed does not append a newline on reading/writing.
Per line overhead: 4 int
s.
When an error occurs, if ed's input is from a regular file or here document, then it exits, otherwise it prints a `?' and returns to command mode. An explanation of the last error can be printed with the `h' (help) command.
If the `u' (undo) command occurs in a global command list, then the command list is executed only once.
Attempting to quit ed or edit another file before writing a modified buffer results in an error. If the command is entered a second time, it succeeds, but any changes to the buffer are lost.
ed exits with 0 if no errors occurred; otherwise >0.