append, change, insert

These three commands come in handy for specific operations as suggested by their names. The substitute command could handle most of the features offered by these commands. But where applicable, these commands would be easier to use.

info Unless otherwise specified, rules mentioned in the following sections will apply similarly for all the three commands.

info The example_files directory has all the files used in the examples.

Basic usage

Just like the substitute command, first letter of these three names represents the command in a sed script.

  • a appends the given string after the end of line for each matching address
  • c changes the entire matching address contents to the given string
  • i inserts the given string before the start of line for each matching address

The string value for these commands is supplied after the command letter. Any whitespace between the letter and the string value is ignored. First up, some examples with a single address as the qualifier.

# same as: sed '2 s/$/\nhello/'
$ seq 3 | sed '2a hello'
1
2
hello
3

# same as: sed '/[24]/ s/.*/hello/'
$ seq 5 | sed '/[24]/c hello'
1
hello
3
hello
5

# same as: sed '2 s/^/hello\n/'
$ seq 3 | sed '2i hello'
1
hello
2
3

Next, some examples with address ranges.

# append and insert is applied for each matching line in the address range
$ seq 5 | sed '2,4i hi there!'
1
hi there!
2
hi there!
3
hi there!
4
5

# change will replace the entire matching range with the given string
$ seq 5 | sed '2,4c hi there!'
1
hi there!
5
# to change every matching line, use the substitute command instead
$ seq 5 | sed '2,4 s/.*/hi there!/'
1
hi there!
hi there!
hi there!
5

Escape sequences

Similar to replacement strings in the substitute command, you can use escape sequences like \t and \n, formats like \xNN and so on.

$ seq 3 | sed '2c rat\tdog\nwolf'
1
rat     dog
wolf
3
$ seq 3 | sed '2a fruit: \x27mango\x27'
1
2
fruit: 'mango'
3

As mentioned before, any whitespace between the command and the string is ignored. You can use \ after the command letter to prevent that.

$ seq 3 | sed '2c         hello'
1
hello
3

$ seq 3 | sed '2c\         hello'
1
         hello
3

As \ has another meaning when used immediately after command letter, use an additional \ if there is a normal escape sequence at the start of the string.

$ seq 3 | sed '2c\nhi'
1
nhi
3

$ seq 3 | sed '2c\\nhi'
1

hi
3

info See also stackoverflow: add newline character if last line of input doesn't have one.

Multiple commands

All the three commands will treat everything after the command letter as the string argument. Thus, you cannot use ; as command separator or # to start a comment. Even command grouping with {} will fail unless you use the -e option or a literal newline character to separate the closing }.

# 'hi ; 3a bye' will treated as a single string argument
$ seq 4 | sed '2c hi ; 3a bye'
1
hi ; 3a bye
3
4
# } gets treated as part of the argument for append, hence the error
$ seq 3 | sed '2{s/^/*/; a hi}'
sed: -e expression #1, char 0: unmatched `{'

# use -e or literal newline to separate the commands
$ seq 4 | sed -e '2c hi' -e '3a bye'
1
hi
3
bye
4
$ seq 3 | sed '2{s/^/*/; a hi
> }'
1
*2
hi
3

Shell substitution

This section is included in this chapter to showcase more examples for shell substitutions and to warn about the potential pitfalls.

# variable substitution
$ text='good\tone\nfood\tpun'
$ seq 13 15 | sed '2c'"$text"
13
good    one
food    pun
15

# command substitution
$ seq 13 15 | sed '3i'"$(date +%A)"
13
14
Wednesday
15

Literal newline in the substituted string may cause an error depending upon the content. To avoid the behavior shown below, process the command output as discussed in the Command substitution section.

$ seq 13 15 | sed '3i'"$(printf 'hi\n123')"
sed: -e expression #1, char 8: missing command

# here, the content after the newline gets executed as a command
# same as: sed -e '3i hi' -e 's/5/five/'
$ seq 13 15 | sed '3i'"$(printf 'hi\ns/5/five/')"
13
14
hi
1five

Cheatsheet and summary

NoteDescription
aappends the given string after the end of line for each matching address
cchanges the entire matching address contents to the given string
iinserts the given string before the start of line for each matching address
string value for these commands is supplied after the command letter
escape sequences like \t, \n, \xNN, etc can be used in the string value
any whitespace between command letter and the string value is ignored
unless \ is the first non-whitespace character after the command letter
so, you'll need an extra \ if the string argument starts with an escape sequence
-e or literal newline is needed to separate any further commands

This chapter covered three more sed commands that work similarly to the substitution command for specific use cases. The string argument to these commands allow escape sequences to be used. If you wish to insert contents from a file literally, then use the commands covered in the next chapter.

Exercises

info The exercises directory has all the files used in this section.

1) For the input file addr.txt, display the third line surrounded by -----.

$ sed ##### add your solution here
-----
This game is good
-----

2) For the input file addr.txt, replace all lines starting from a line containing you till the end of file with a blank line followed by Have a nice day.

$ sed ##### add your solution here
Hello World

Have a nice day

3) For the input file addr.txt, replace even numbered lines with ---.

$ sed ##### add your solution here
Hello World
---
This game is good
---
12345
---