sed Cheatsheet
One-Liners
Use this sed reference while you build software engineering projects, review code, or refresh the syntax you reach for most.
Printing and selecting
sed -n '5p' file # print line 5 sed -n '2,4p' file # lines 2 through 4 sed -n '$p' file # last line, like tail -1 sed -n '5q;p' file # first 4 lines, like head -4, no SIGPIPE sed -n '/re/p' file # like grep sed -n '/re/!p' file # like grep -v sed -n '/re/Ip' file # like grep -i sed -n '/re/{p;q;}' file # first match only, then stop reading sed -n '$=' file # line count, like wc -l sed -n '/re/=' file # line numbers of matches sed -n '/^.\{65\}/p' file # lines longer than 64 characters sed -n 'n;n;p' file # every third line, portable gsed -n '0~3p' file # every third line. GNU only
sed -n '5q;p' beats head -4 inside a pipeline that must not die early, and
sed -n '500000,500010p;500011q' reads a slice of a huge file without scanning
the rest.
Deleting
sed '5d' file # drop line 5 sed '2,4d' file # drop a range sed '$d' file # drop the last line sed '1,2d' file # skip a two-line header sed '/^$/d' file # drop every blank line sed '/^[[:space:]]*$/d' file # drop whitespace-only lines too sed '/^#/d;/^$/d' file # strip comments and blanks from a config sed '/re/,$d' file # from the first match to end of file sed '/^begin$/,/^end$/d' file # drop a marked block sed '/^$/{N;/^\n$/D;}' file # squeeze runs of blanks down to one
- d starts the next cycle immediately, so nothing after it in the script runs.
- The blank-squeeze needs the ; before } to work on BSD sed. See the
addresses topic for why.
Substituting
sed 's/old/new/' file # first match on each line sed 's/old/new/g' file # every match sed 's/x/Y/3' file # the third match only gsed 's/x/Y/3g' file # third match onward. GNU only, BSD errors sed 's/[[:space:]]\{1,\}/ /g' file # collapse runs of whitespace sed 's/^/> /' file # quote a mail reply sed 's/$/;/' file # append to every line sed 's|/usr/local|/opt|g' file # alternate delimiter, no escaping needed sed 's/<[^>]*>//g' file # crude tag stripper sed 's/\(.*\)\//\1|/' file # change the LAST slash, thanks to greedy .* sed '5!s/a/b/' file # everywhere except line 5 sed '/^#/!s/a/b/' file # skip comment lines
The greedy trick is the standard way to reach the last occurrence. .* grabs as
much as it can, so the / that follows it is the final one on the line.
Whitespace and line endings
sed 's/^[[:space:]]*//' file # trim leading sed 's/[[:space:]]*$//' file # trim trailing sed 's/^[[:space:]]*//;s/[[:space:]]*$//' file # trim both sed 's/\r$//' file # CRLF to LF, dos2unix sed 's/$/\r/' file # LF to CRLF, unix2dos sed -n '/\r$/l' file # find the CR-terminated lines sed 's/\t/ /g' file # tabs to four spaces sed 's/ */\t/g' file # spaces to tabs
\t and \n work in patterns on both macOS sed and GNU sed, but they are not POSIX,
so busybox and older systems may take them literally. The safe form is a real tab,
which you get in a shell with $'\t' or by pressing ctrl-v then tab.
sed "s/$(printf '\t')/ /g" file # portable tabs to spaces sed $'s/\t/ /g' file # bash and zsh, also portable to BSD sed
Reversing, numbering, joining
sed '1!G;h;$!d' file # reverse the file, like tac sed -n '1!G;h;$p' file # same thing, shorter to read sed '/\n/!G;s/\(.\)\(.*\n\)/&\2\1/;//D;s/.//' # reverse each line, like rev sed = file | sed 'N;s/\n/\t/' # number lines, like cat -n sed G file # double-space sed 'n;d' file # undo double-spacing sed -e :a -e '$q;N;3,$D;ba' file # last 2 lines, like tail -2 sed -e :a -e 'N;$!ba' -e 's/\n/,/g' file # join all lines with commas sed '$!N;s/\n/ /' file # join lines in pairs sed '$!N; /^\(.*\)\n\1$/!P; D' file # like uniq
The tac trick works because G appends the hold space to the pattern space and
h copies it back, so the hold space accumulates the file in reverse. $!d
suppresses everything until the last line.
Blocks and paragraphs
sed -n '/BEGIN/,/END/p' file # the block, markers included sed -n '/BEGIN/,/END/{//!p;}' file # the block, markers excluded sed '/BEGIN/,/END/d' file # everything but the block sed -n '/re/{=;p;}' file | sed 'N;s/\n/:/' # like grep -n # print every blank-line-separated paragraph that contains foo sed -e '/./{H;$!d;}' -e 'x;/foo/!d' file # reflow each paragraph onto one line sed -e '/./{H;$!d;}' -e 'x;s/\n/ /g;s/^ //;p' -e d file
- // reuses the last regex, which is how the marker-excluding form stays short.
- The paragraph idioms emit a leading blank line, because the hold space starts
out holding a newline. Pipe through sed '1{/^$/d;}' if that matters.
Insert, append, and quit
sed $'1i\\\nHEADER' file # prepend a line, bash or zsh sed $'$a\\\nFOOTER' file # append a line sed $'/^\\[main\\]$/a\\\nkey = value' config # add under a section gsed '1i HEADER' file # GNU only one-line form sed '1r header.txt' file # splice a file in after line 1 sed '$r footer.txt' file # splice a file in at the end sed '10q' file # stop after 10 lines sed '/^done$/q' file # stop at a sentinel gsed '/error/q1' file # exit 1 if a match was seen. GNU only
Which of these are not portable
| One-liner | Status |
|---|---|
s/x/Y/Ng with a number and g | GNU only, BSD refuses both flags |
0~3p, 1~2d step addresses | GNU only |
\+ \? \w in a pattern | GNU, or BSD with -H. Plain BSD takes them literally |
\s in a pattern | GNU only, use [[:space:]] |
l N wrap width | GNU only, BSD l takes no argument |
1i TEXT on one line | GNU only, POSIX needs a backslash newline |
q1 exit code, Q, T, W, z, F | GNU only. BSD also exits 1, but on a parse error, so $? lies |
-i with no argument | GNU only, BSD needs -i '' |
:a;p;ba labels joined by ; | GNU only, BSD reads a;p;ba as the label |
{cmd} with no ; before } | GNU only, BSD wants {cmd;} |
Everything else on this page was checked byte for byte against macOS sed and GNU
sed 4.10, and behaves identically on both. A minimal sed such as busybox was not
tested, and the \t caveat above is the one spot to watch there.
When a script has to be portable and readable at once, write one -e per command
and stop fighting the quoting.