Part III · Shell and commands
28.4 sed
alsosedreplace textsearch and replacefind and replacesubstitute
TL;DR
sededits text line by line as it flows through. Its most used command iss/old/new/.- Without
g, only the first match on each line changes;s/old/new/gchanges them all. -iedits the file in place. GNU sed (Linux) takes-ialone; macOS needs-i ''.
sed 's/http:/https:/g' links.txt
sed -i.bak 's/DEBUG=1/DEBUG=0/' .env # keeps a copy in .env.bak
sed -n '10,20p' big.log # print lines 10 to 20
Pitfalls
- Run the command without
-ifirst and read the output:-ihas no undo, unless you give it a suffix like-i.bak. - When the text contains
/, use another separator:s|/usr/local|/opt|. - In the replacement,
&means "what matched": write\&for a literal ampersand. - As with grep,
+and|need-Eto have their usual meaning. sed -ion a symbolic link replaces the link with a regular file, unless you add--follow-symlinks.
Deep dive 2 questions
How does sed work?
It reads one line, runs the script on it, prints the result, then moves to
the next line. -n turns off the automatic printing, so only p prints.
A command can be limited to some lines with an address in front: /^#/d
deletes comment lines, 5,10s/a/b/ only replaces on lines 5 to 10, and
/start/,/end/ covers everything between two matches.
How do I reuse part of the match?
With -E, parentheses capture, and \1, \2 bring the captures back in
the replacement. This swaps "user@host" into "host: user":
sed -E 's/([a-z]+)@([a-z.]+)/\2: \1/' contacts.txt