sed Cheatsheet
Addresses and Ranges
Use this sed reference while you build software engineering projects, review code, or refresh the syntax you reach for most.
Address forms
An address selects which lines a command runs on. Zero, one, or two addresses, depending on the command.
| Address | Selects | Portable? |
|---|---|---|
| (none) | every line | POSIX |
N | line N, counted across all input files | POSIX |
$ | the last line of the last file | POSIX |
/re/ | lines matching the BRE (or ERE with -E) | POSIX |
\cREc | the same, with c as the delimiter | POSIX |
/re/I | case-insensitive match | both, not POSIX |
/re/M | multiline match | GNU only |
first~step | every stepth line starting at first | GNU only |
0,/re/ | up to the first match, even on line 1 | GNU only |
addr1,addr2 | from addr1 through addr2 | POSIX |
addr1,+N | addr1 plus the next N lines | GNU, and works on macOS |
addr1,~N | addr1 through the next line number divisible by N | GNU only |
addr! | invert, every line the address does not select | POSIX |
sed -n '5p' file # line 5 sed -n '$p' file # last line sed -n '/^Host/p' file # matching lines sed -n '\|/etc/|p' file # alternate delimiter, no escaped slashes sed -n '/warn/Ip' file # case-insensitive sed '5d' file # everything except line 5 sed -n '5!p' file # the same thing, inverted
Ranges
addr1,addr2 turns on at the first line matching addr1 and off at the next line
matching addr2.
sed -n '10,20p' file # lines 10-20 inclusive sed -n '10,$p' file # line 10 to the end sed -n '/BEGIN/,/END/p' file # inclusive block sed -n '/BEGIN/,$p' file # from the marker to EOF sed -n '2,+3p' file # line 2 and the 3 after it sed '/^#/,/^$/d' file # comment block to the next blank line
The rules that trip people up:
- addr2 is tested starting on the line after addr1 matched. A single line
matching both patterns still opens the range, and it closes later. This is the
opposite of awk, where /a/,/b/ on one line is a one-line range.
- If addr2 never matches, the range runs to end of input.
- A range restarts. /A/,/B/ fires again every time A appears after a B.
- If addr2 is a line number less than or equal to the line where addr1
matched, only that one line is selected.
- 1,/re/ skips a match on line 1, because addr2 is tested from line 2. GNU's
0,/re/ exists precisely to fix that.
printf 'A\nx\nA\ny\n' | sed -n '1,/A/p' # A x A <-- surprising printf 'A\nx\nA\ny\n' | gsed -n '0,/A/p' # A <-- GNU only printf 'A\nx\n' | sed -n '/A/,3p' # A x <-- addr2 clamps
Step and modulo addresses (GNU only)
gsed -n '1~2p' file # odd lines gsed -n '0~2p' file # even lines gsed -n '2~5p' file # line 2, 7, 12, ... gsed -n '3,~4p' file # line 3 through the next multiple of 4
Portable equivalents, since macOS sed rejects ~ outright:
awk 'NR % 2' file # odd lines awk 'NR % 2 == 0' file # even lines sed -n 'p;n' file # odd lines, pure sed sed -n 'n;p' file # even lines, pure sed
Negation
! after the address inverts it. It attaches to the address, not the command.
sed -n '3!p' file # everything but line 3 sed '/^#/!d' file # keep ONLY comment lines sed '1,10!d' file # keep only the first 10 lines sed -n '/BEGIN/,/END/!p' file # everything outside the block sed '$!N' file # append the next line, except on the last line
$!N is the workhorse. It stops N from quitting early on a file with an odd line
count, which is the difference between "joins pairs of lines" and "silently drops the
last line".
Blocks and multiple commands
{ } groups commands under one address. On BSD sed every command inside the block,
including the last one, must be terminated by ; or a newline.
# GNU: fine. BSD: "extra characters at the end of p command" sed -n '/^Host/{s/Host/H/;p}' config # portable: note the semicolon before the closing brace sed -n '/^Host/{s/Host/H/;p;}' config # also portable, one -e per command sed -n -e '/^Host/{' -e 's/Host/H/' -e 'p' -e '}' config
Nesting works, and each level may carry its own address:
sed -n '/^\[section\]/,/^\[/{
/^key/{
s/=.*/=newvalue/
p
}
}' config.iniWritten across real newlines like that, the terminator issue disappears, which is
why anything non-trivial belongs in a -f script file.
Address cheat sheet by command
| Command | Addresses accepted |
|---|---|
= a i r q Q F | one (GNU allows two for a i r) |
s y d D p P l n N h H g G x w W z c | zero, one, or two |
b t T : | : takes none, the branches take zero, one, or two |
{ | zero, one, or two |
Q T W z F R are GNU-only commands. macOS sed answers invalid command
code for each of them.
sed '2q' file # print 2 lines and stop, like head -2 sed '1,3d' file # two addresses on d sed '2,4c\ REPLACED' file # c on a range collapses it to one line