## 5.5. Append, Insert, and Change

The append (a), insert (i), and change (c) commands provide editing functions that are commonly performed with an interactive editor, such as vi. You may find it strange to use these same commands to "enter" text using a noninteractive editor. The syntax of these commands is unusual for sed because they must be specified over multiple lines. The syntax follows:

>     append	[line-address]a\
>     	text
>     insert	[line-address]i\
>     	text
>     change	[address]c\
>     	text

The insert command places the supplied text before the current line in the pattern space. The append command places it after the current line. The change command replaces the contents of the pattern space with the supplied text.

Each of these commands requires a backslash following it to escape the first end-of-line. The `text` must begin on the next line. To input multiple lines of text, each successive line must end with a backslash, with the exception of the very last line. For example, the following insert command inserts two lines of text at a line matching "<Larry's Address>":

>     /<Larry's Address>/i\
>     4700 Cross Court\
>     French Lick, IN

Also, if the text contains a literal backslash, add an extra backslash to escape it.[31]

> [31]The original UNIX documentation says that any leading tabs or spaces in the supplied text will disappear on output. This is the case on older versions, such as SunOS 4.1.x and /usr/ucb/sed on Solaris. System V and GNU sed do not delete the leading whitespace. If they disappear on your system, the solution is to put a backslash at the beginning of the line, preceding the first tab or space. The backslash is not output.

The append and insert commands can be applied only to a single line address, not a range of lines. The change command, however, can address a range of lines. In this case, it replaces all addressed lines with a single copy of the text. In other words, it deletes each line in the range but the supplied text is output only once. For example, the following script, when run on a file containing a mail message:

>     /^From /,/^$/c\
>     <Mail Header Removed>

removes the entire mail-message header and replaces it with the line "<Mail Header Removed>." Note that you will see the opposite behavior when the change command is one of a group of commands, enclosed in braces, that act on a range of lines. For instance, the following script:

>     /^From /,/^$/{
>     	s/^From //p
>     	c\
>     <Mail Header Removed>
>     }

will output "<Mail Header Removed>" for each line in the range. So, while the former example outputs the text once, this example will output it 10 times if there are 10 lines in the range.

The change command clears the pattern space, having the same effect on the pattern space as the delete command. No command following the change command in the script is applied.

The insert and append commands do not affect the contents of the pattern space. The supplied text will not match any address in subsequent commands in the script, nor can those commands affect the text. No matter what changes occur to alter the pattern space, the supplied text will still be output appropriately. This is also true when the default output is suppressed--the supplied text will be output even if the pattern space is not. Also, the supplied text does not affect sed's internal line counter.

Let's look at an example of the insert command. Suppose we wanted to source a local file of macros in all the files of a particular document. In addition, we'd like to define a page header string that identifies the document as a draft. The following script inserts two new lines of text before the first line of a file:

>     1i\
>     .so macros\
>     .ds CH First Draft

After sed executes this command, the pattern space remains unchanged. The new text is output before the current line. A subsequent command could not successfully match "macros" or "First Draft."

A variation of the previous example shows the append command adding a line to the end of a file:

>     $a\
>     End of file

The $ is a line-addressing symbol that matches the last line of a file. The supplied text will be output after the current line, so it becomes the last line in the output. Note that even though only one line is output, the supplied text must start on a line by itself and cannot be on the same line as the append command.

The next example shows the insert and append commands used in the same script. The task here is to add a few troff requests before the macro that initializes a list, and several after the macro that closes the list.

>     /^\.Ls/i\
>     .in 5n\
>     .sp .3
>     /^\.Le/a\
>     .in 0\
>     .sp .3

The insert command puts two lines before the .Ls macro and the append command puts two lines after the .Le macro.

The insert command can be used to put a blank line before the current line, or the append command to put one after, by leaving the line following it blank.

The change command replaces the contents of the pattern space with the text you provide. In effect, it deletes the current line and puts the supplied text in its place. It can be used when you want to match a line and replace it entirely. Let's say for instance that a file contains a lot of explicit troff spacing requests with different amounts of spacing. Look at the following series:

>     .sp 1.5
>     .sp
>     .sp 1
>     .sp 1.5v
>     .sp .3v
>     .sp 3

If you wanted to change all the arguments to ".5", it is probably easier to use the change command than try to match all the individual arguments and make the proper substitution.

>     /^\.sp/c\
>     .sp .5

This command allows us to ignore the arguments and replace them regardless of what they are.

Copyright © 2003 O'Reilly & Associates. All rights reserved.