ed

NAME

ed - line-oriented text editor

SYNOPSIS

ed [-p prompt-string] [-s] [-v] [filename]

DESCRIPTION

The ed(1) utility is a powerful, line-oriented editor. Although ex(1) and vi(1) have gained popularity, ed(1) still maintains advantages over them. Some of the most notable advantages of ed(1) are: the W command, described later in this topic and which is not part of ex(1) or vi(1); the smaller executable size (you can often begin editing before the others finish loading); and the better response when editing from slow terminals or across low-baud data lines. The ed(1) utility continues to be used by many system utilities.

When a filename is present, ed(1) starts by simulating an e command (described later in this topic). If no file name is present ed(1) starts with an empty buffer.

OPTIONS

The ed(1) utility accepts the following options:

-p prompt-string
Set the prompt to prompt-string. The default prompt is *. (See also the P command.)
-s
Suppress the printing of explanatory output from the commands e, E, r, w, W and wq. This option should be used with a script.
-v
Display a message that describes which of BSD or POSIX mode ed(1) has been set. This is useful for determining the behavior described in the following section.

BEHAVIOR

The ed(1) utility performs all changes to a copy of the file that is contained in a buffer. For the changes to have an effect, one of the write commands (w, W, wq, or Wq) must be issued.

The contents of the buffer can changed by issuing commands that are lead by zero, one, or two addresses. All commands are alphabetically listed below, with their parameter structures if applicable. Trailing structures not described with commands are regarded as erroneous. Commands that accept zero addresses regard the presence of any address as an error.

The ed(1) utility works in two modes: command, and input. The two modes are exclusive of each other. While in command mode, ed(1) accepts commands that display, modify, or give information about the buffer. While in input mode ed(1) accepts lines of text to be added to the buffer.

Addressing in ed(1) specifies one or more lines contained in the buffer. For commands that expect at least one address, if none are given, default addresses will be used. To use addresses in ed(1), it is important to know that, during the execution of most ed(1) commands, a current line (current) exists. Current is usually the location in the buffer that the last command issued affected, although some commands do not affect current. Each command description (discussed later) describes its affects on current.

ADDRESSES

Addresses can be divided into three cases: one address (single address), two addresses (an address pair), and special address forms.

For the first two cases, an address is formed with the following:

  1. A positive decimal integer (such as 123), indicating a line number in the buffer. Line number 1 is the first line in the buffer.
  2. The period (.), indicating the current line (current).
  3. The dollar sign ($), which indicates the last line in the buffer.
  4. A regular expression (RE) enclosed with forward slashes (/) as delimiters (that is, /RE/). This causes a forward search to the first occurrence of the specified RE. The address will then become this line. The character sequence "\/" escapes the forward slash from being a delimiter. The search will wrap from the bottom of the buffer to the top of the buffer if necessary. The ed(1) utility REs are, outside of this document, now referred to as basic regular expressions. Basic regular expressions (BREs) are those that have traditionally worked in ed(1). BREs are, for the most part, the same as the old REs—the name has changed and the expressions have been extended to meet POSIX 1003.2 specifications. (See the search command for more details.)
  5. An RE enclosed with question marks (?) as delimiters (that is, ?RE?). This will cause a backward search to the first occurrence of the specified BRE. The address will then become this line. The character sequence \? escapes the question mark from being a delimiter. The search will wrap from the top of the buffer to the bottom of the buffer if necessary. (See the search command for more details.)
  6. A line previously marked by the k command (described later). 'x addresses the line marked by the single lowercase letter 'x' (from the portable character set in the range a-z).
  7. An address of the form 1-6, followed by a '+', followed by an integer number, n. This specifies that the line to be addressed is n lines after the address of the form 1-6. If the address starts with a '+', by default, the addressed line is taken with respect to current (equivalent to '.'; form 2). If no integer number is given, 1 is added to the address. If more than one '+' is given in a sequence, with no integer number following, 1 is added to the address for each '+'. Therefore, +++ is equivalent to +3, but +++1 is equivalent to +1.
  8. An address of the form 1-6, followed by a '-', followed by an integer number, n. This specifies that the line to be addressed is n lines before the address of the form 1-6. If the address starts with a '-', by default the addressed line is taken with respect to current ('.'; form 1). If no integer number is given, 1 is subtracted from the address. Hence, if more than one '-' is given in a sequence, with no integer number following, 1 is subtracted from the address for each '-'. Therefore, --- is equivalent to -3, but ---1 is equivalent to -1. For backward compatibility '^' is the equivalent to '-'.
  9. A comma (,) can be used to separate two addresses of the form 1-8 to create an address pair. The first address must occur no later in the buffer than the second address to be legal.
  10. A semicolon (;) can be used to separate two addresses of the form 1-8 to create an address pair. With this form, the second address is evaluated with respect to and after the first address has been evaluated. This is useful when addresses of the forms 2-8 are used. The first address must occur no later in the buffer than the second address to be legal.

Addresses of the forms 7 and 8 cannot be followed by addresses of forms 2-6; doing so is an error.

The following are special address forms that cannot be combined with any of the address forms listed above. A ',' by itself represents the address pair '1,$'. Likewise '%' by itself represents the address pair '1,$'. A ';' by itself represents the address pair '.,$'.

COMMANDS

The ed(1) commands listed below default to the addresses prefixing the commands. Commands without default addresses accept zero addresses. The parentheses with the default addresses are not part of the address; they are used to show that the addresses are default.

Generally, only one command appears on a line at a time. However, many of the commands may be suffixed by l, n, or p, in which case the current line is printed in the manner discussed in the following list. These suffixes may be combined in any order.

(.)a
text
.
Append text after the addressed line. A '.' in the first column, followed immediately by a newline, places ed(1) back in command mode the '.' is not included in the text. Line 0 is legal for this command; text will be placed at the top of the buffer. Current is the last line appended (or the addressed line if no text given).
(.,.)c
text
.
Change text on one or more addressed lines. The addressed lines are deleted before ed(1) is placed in input mode. A '.' in the first column, followed immediately by a newline, places ed(1) back in command mode the '.' is not included in the text. Current is the new last line appended (or if no text is given the line after the addressed line deleted).
(.,.)d
Delete the addressed line(s) from the buffer. Deleted lines may be recovered with the undo command (u; see below). Current is the line after the last addressed line deleted.
e [filename]
Edit the new file filename. The buffer is cleared and the new file is placed in the buffer. If the buffer has been modified since the last write command, ed(1) will issue a warning ('?'); a second issuing of the command will be obeyed regardless. The number of characters read is printed (unless -s is specified at startup). If filename is missing, the remembered name is used. If filename is lead by a '!', it will be interpreted as a shell command to be executed, from which the standard output will be placed into the buffer; filename will be non-remembered. "Undo" will not restore the buffer to its state before the edit command. Current is the last line in the buffer ('$').
E [filename]
E works the same as e, except that if the buffer has been modified, no warning is issued.
f [filename]
Print the remembered filename. If filename is specified, the remembered filename is set to filename. If filename is lead by !, it is interpreted as a shell command to be executed, from which the standard output is be used as the new remembered file name. Current is unchanged.
(1,$)g/regular expression/command list
The global command first marks all lines matching the regular expression. For each matching line, the command list is executed. At the start of each command list execution, current is set to equal that line; current may change as each command in the command list is executed for that line. The first command of the command list begins on the same line as the global command. In the command list, one command usually occupies a line. To have multiple commands in the command list, you must escape the newline at the end of each line so that the global command does not interpret it as an indication that the command list entry has ended. The newline is escaped by proceeding it with a backslash (\). Similarly, with the commands that set ed(1) into input mode, the newlines of the entered text must be escaped. If the '.' used to end input mode is the last line of the command list, the newline following the '.' need not be escaped, or the '.' may be omitted entirely. Commands in the command list can affect any line in the buffer. For information about the behavior of each ed(1) command within a command list, refer to the information on the individual command, particularly s and !. The commands g, G, v, V, and ! are permitted in the command list, but should be used with caution. The command list defaults to p if left empty (that is, g/RE/p). For the regular expression, the delimiters can be any characters except space and newline; delimiters within a regular expression can be escaped with a backslash preceding it.
(1,$)G/regular expression/
The interactive global command works very much like g. The first step is to mark every line that matches the given regular expression. For every line matched, it will print this line, set current to this line, and accept one command (not including a, c, i, g, G, v, and V) for execution. The command can affect any line in the buffer. '%' by itself executes the last non-null command. A return by itself acts as a null command. Current is set to the last line affected by the last successful command input. If no match or an input command error occurs, current is set to the last line searched by G. G can be prematurely ended by (SIGINT). For information about the behavior of each ed(1) command within a command list, refer to the information on the individual command, particularly s and !.
h
The help command displays a message explaining the most recent command error (indicated by '?'). Current is unchanged.
H
This toggles on or off the automatic display of messages explaining the most recent command error in place of '?'. Current is unchanged.
(.)i
text
.
The insert command places ed(1) in input mode, and places the text before the addressed line. Line 0 is invalid for this command. A period (.) in the first column, followed immediately by a return, places ed(1) back in command mode.The '.' is not included in the text. Current is the last line inserted. If no text is inserted, current is the addressed line.
(.,.+1)j
The join command joins the addressed lines together to make one line. If no addresses are specified, the current and current lines are joined. If only one address is given, no join is performed. Current is unchanged.
( . )kx
The mark command marks the addressed line with label x, where x is a lowercase letter from the portable character set (a-z). The address form 'x will refer to this line (address form 6 above). Current is unchanged.
(.,.)l
The list command prints the addressed lines in an unambiguous way: non-graphic characters are printed in three-digit octal, preceded by a backslash (\) unless they are one of the following, in which case they will be printed as indicated in the parentheses: backslash (\\), horizontal tab (\t), form feed (\f), return (\r), vertical tab (\v), and backspace (\b). Long lines will be broken based on the type of terminal currently in use and will likely be ragged at the right side if text and octal are mixed on the same line. Current is set to the last line printed. The l command may be placed on the same line after any command except (e, E, f, q, Q, r, w, W, or !).
(.,.)ma
The move command moves the addressed lines in the buffer to after the address a. Line 0 is valid as the address a for this command. Current is the location in the buffer of the last line moved.
(.,.)n
The number command prints the addressed lines preceding the text with the line number. The n command can be placed on the same line after any command except (e, E, f, q, Q, r, w, W, or !). Current is the last line printed.
(.,.)p
The print command prints the addressed lines. The p command can be placed on the same line after any command except (e, E, f, q, Q, r, w, W, or !). Current is the last line printed.
(.,.)P
The prompt is toggled on or off. Current is unchanged. The default prompt is "*" if not specified with the -p option at startup. The prompt is initially off unless the -p option is specified.
q
The quit command causes ed(1) to exit. If the entire buffer (1,$) has not been written since the last modification, ed(1) issues a warning once ('?'); a second issuing of the command will be obeyed regardless.
Q
Q works the same as q, unless the buffer has been modified, in which case, no warning is issued.
($)r [filename]
The read command reads in the file filename after the addressed line. If no filename is specified, the remembered filename is used. Address 0 is valid for this command. If read is successful, the number of characters read is printed (unless the -s option is specified). If filename is lead by exclamation mark (!), it will be interpreted as a shell command to be executed, from which the standard output will be placed in the buffer; filename will be non-remembered. Current is the last line read.
( ., .)s/regular expression/replacement/flags
The substitute command searches for the regular expression in the addressed lines. On each line in which a match is found, matched strings are replaced by the replacement, as specified by the flags (described later). If no flags appear, by default, only the first occurrence of the matched string in each line is replaced. It is an error if no matches to the RE occur.

The delimiters may be any character except space or newline. The delimiter lead by a '\' will escape it to be a literal in the RE or replacement.

An ampersand, (&) appearing in the replacement will equal the string matching the RE. The special meaning of & can be suppressed by leading it with a '\'. When '%' is the only replacement character in replacement, the most recent replacement is used. The special meaning of '%' can be suppressed by leading it with a '\'.

The characters \n (where n is a digit 1-9) is replaced by the text matching the RE subexpression n (known as back referencing). S can be used to break lines by including a newline in replacement, preceded by a '\' to escape it. Replacement can continue on the next line and can include another escaped newline.

The following extension should not be included in portable scripts. When splitting lines using s within the global commands (g, G, v, or V) the newline in the replacement string must be escaped by preceding it with '\\\' (three adjacent backslashes; the first '\' escapes the second '\' so that it is passed to s to escape the newline passed by the global command; the third '\' is to escape the newline so that the global command list continues). (N.B. Other ed(1) implementations do not allow line splitting within the global commands.)

The flags may be any combination of:

count
In each addressed line, replace the instance of the matching occurrence specified by count.
g
In each addressed line, replace all matching occurrences. When count and g are specified together, inclusively replace in each addressed line all matches from the instance of matching specified by countto the end of line.
l
Write the line after replacement in the manner specified by the l command.
n
Write the line after replacement in the manner specified by the n command.
p
Write the line after replacement in the manner specified by the p command.

The following special form should not be included in portable scripts. This form is maintained for backward compatibility and is extended to dovetail into the above forms of s. S followed by no delimiters repeats the most recent substitute command on the addressed lines. S can be suffixed with the letters r (use the most recent RE rather than the last RE used with s), p (complement the setting of the any print command (l n, p) suffix from the previous substitution), g (complement the setting of the g suffix) or N (negate the previous count flag). These modifying letters may be combined in any order (N.B. multiple use of the modifying letters may cause them to be interpreted as delimiters).

Current is set to where the last replacement occurred (POSIX).

(.,.)ta
The transcribe command copies the addressed lines in the buffer to after the address a. Address 0 is valid as the address a for this command. Current is the last line transcribed.
(.,.)u
The undo command nullifies the most recent buffer-modifying command. The undo command reverses the following buffer-modifying commands:a, c, d, g, G, i, j, m, r, s, t, u, v, and V. Marks set by the k command will also be restored. All commands (including nested g, G, v, and V commands within the g or v) that undo reverses are treated as a single buffer modification. Current is set to the line it addressed before the last buffer modification.
(1, $)v/regular expression/command list
The global nonmatching command performs as the g command does, except that the command list is executed for every line that does not match the RE.
(1, $)V/regular expression/
The interactive global nonmatching command is the same as G, except that one command will be accepted as input with current initially set to every line that does not match the RE.
(1, $)w [filename]
The write command writes the addressed lines to the file filename. If no filename is specified, the remembered filename is used. If no addresses are specified, the whole buffer is written. If the command is successful, the number of characters written is printed (unless the -s option is specified). If filename is lead by !, it will be interpreted as a shell command to be executed which will accept on its standard input the section of the buffer specified for writing. Current is unchanged.
(1, $)W [filename]
W functions like the w command does, except that the addressed contents of the buffer are appended to filename (or the remembered filename if filename is not specified). If filename is lead by !, W will act exactly as the w command. Current is unchanged.
(1, $)wq [filename]
wq works just as the w command does, except that, in addition, ed(1) exits immediately after the write is complete. Current is unchanged.
(1,$)Wq [filename]
Wq works as the W command does, except that, in addition, ed(1) exits immediately after the appended write is complete. Current is unchanged.
(.+1)z
(.+1)zn
Scroll through the buffer. Starting from the addressed line (or current +1), print the next 22 (by default) or n lines. The n is a sticky value; it becomes the default number of lines printed for successive scrolls. Current is the last line printed.
($)=
Print the number of lines in the buffer. If an address is provided (in the forms 1-8 above), the line number for that line will be printed. Current is unchanged.
!shell command
The command after the ! is executed by sh(1), and the results are printed. A '!' is printed in the first column when execution has completed (unless the -s option has been specified). A '!' immediately after ! repeats the last shell command. An unescaped '%' represents the remembered file name. Commands to sh(1) can have several lines by escaping the newline with a '\' immediately before it. The line-continuation character for sh(1), backslash (\) can be included on a line provided that it is escaped by a backslash (\) immediately before, so that ed(1) passes it literally to sh(1): '\\'. It is implicit that, for the command line that the sh(1) line-continuation character is on, the newline will be escaped (such as '\\\newline'). This behavior can be used within global command lists. However, an additional backslash (\) must be added so that the ! command continuator is passed to !. It must occur immediately before the global command's continuator. Therefore, the ! command-continuation sequence in a global command list will appear as '\\\' (explanation as with s). The line-continuation character for sh(1) needs no additional escaping (since it is not dependent on newline being adjacent). Hence, the sequence in a global command list with a line continuation will appear as '\\\\\newline'. Current is unchanged.
/regular expression/
?regular expression?
The search command searches forward, '/', (or backward, '?') through the buffer, attempting to find a line that matches the RE. The search will wrap to the top (or bottom) of the buffer if necessary. Search returns the line number on which the match occurs, combined with the null command. This causes the line to be printed. Current is the matching line.
(.+1,.+1)newline
The null command is equivalent to asking for the line current to be printed according to the p command. This command can be used to print the next few lines quickly. If more than a few lines are needed, however, it is better to use the z command described previously. Current is the last line printed.

OTHER

If an interrupt signal (SIGINT) is sent, ed(1) prints '?' and returns to command mode.

BSD command pairs are permitted. Additionally, any single-print command can follow any of the non-I/O commands (I/O commands: e, E, f, r, w, W, wq, and !). This will cause the current line to be printed in the specified manner after the command has completed.

Previous limitations on the number of characters per line and per command list have been lifted; there is now no maximum. File name and path length are restricted to the maximum length that the current file system supports. The undo command now restores marks to affected lines. The temporary buffer method will vary, depending on the method selected at compile. Two methods work with a temporary file (stdio and db), while the third uses memory. The limit on the number of lines depends on the amount of memory.

FILES

/tmp/_bsd44_ed*
The temporary file.
ed.hup
ed.hup: the buffer is written to this file in the current directory if possible and in the HOME directory is not (if the signal SIGHUP (hangup) is received).

DIAGNOSTICS

'?name' for a file that is inaccessible, does not exist, or is a directory. '?' for all other errors unless the help messages have been toggled on (with the H command), in which case a descriptive message will be printed.

EOF is treated as a newline during input so that characters after the last newline are included into the buffer; the message "newline added at end of line" is printed.

The ed(1) utility returns an exit status of 0 on successful completion. A value >0 is returned to indicate an ed(1) error: 1 for a command line error, 2 for HUP signal received, 4 for an ed(1) command error; these error values will be combined using a bitwise OR when appropriate.

SEE ALSO

sed(1)