terminal:scripting:sed
Table of Contents
sed
Stream editor: applies edit commands to each line. GNU sed on Ubuntu.
The one command you'll use 95% of the time
sed 's/old/new/' # substitute, first match per line sed 's/old/new/g' # all matches per line sed 's/old/new/2' # only the 2nd match per line sed -i 's/old/new/g' f # edit file in place sed -i.bak 's/x/y/' f # in place, keeps f.bak sed -E 's/(a)(b)/\2\1/' # extended regex + backrefs
Any delimiter works: useful for paths/URLs: sed 's|/a/b|/x/y|g'.
& in replacement = the whole match: sed 's/foo/[&]/g' → [foo].
Addressing: //which// lines get the command
sed '5d' f # delete line 5 sed '5,10d' f # delete 5-10 sed '$d' f # last line sed '2~3d' f # every 3rd line starting at 2 sed '/error/d' f # lines matching /error/ sed '/START/,/END/d' f # inclusive pattern range sed '/START/,/END/!d' f # keep ONLY the range (! inverts) sed -n '5,10p' f # print just lines 5-10 (-n + p) sed -n '/error/p' f # print only matches (grep-like)
The commands beyond `s`
d delete line p print line (with -n) a\ append after line i\ insert before line c\ change whole line y/abc/ABC/ transliterate chars
sed '3i\inserted text' f # insert before line 3 sed '/pattern/a\appended' f # append after matches sed 'y/abc/ABC/' f # like tr, per char sed -n 's/x/y/p' f # print only changed lines
Multiple commands
sed -e 's/a/b/' -e '5d' f sed 's/a/b/; s/c/d/' f # ; separates commands sed '/skip/!s/a/b/' f # s on lines NOT matching
Useful regex bits (GNU sed BRE/ERE)
- Default is BRE:
+,?,(,),|need backslashes.
sed 's/\(ab\)\+/X/: or just always use sed -E (ERE) and forget it.
\bword boundary,\w/\W,\s/\Swork in GNU sed.\( \)groups become\1-\9backrefs:sed -E 's/([0-9]+)x([0-9]+)/\2 by \1/'..*is greedy:sed -E 's/“(.*)”/\1/' grabs the LAST quote pair.
Non-greedy needs [^“]*: sed -E 's/”([^“]*)”/\1/'.
Classic one-liners
sed 's/^[[:space:]]*//;s/[[:space:]]*$//' f # trim whitespace sed 's/^/# /' f # comment out every line sed -n 'x;$p' f || tail -1 f # last line (use tail) sed -e :a -e 'N;$!ba' -e 's/\n/ /g' f # join all lines sed 's/./&\n/g' f # one char per line seq 5 | sed 's/^/item/' # generate
Gotchas
-iwithout backup is irreversible: test without-ifirst.sed -i '' is macOS syntax; GNU issed -i(no arg). These pages assume
GNU sed on Linux.
sed -ztreats input as NUL-separated: for filenames fromfind -print0.- It processes line-by-line; multi-line matching needs
N,P,D: at that
point reach for perl -0777 -pe or awk.
See Also
terminal/scripting/sed.txt · Last modified: by 127.0.0.1
