Why this lesson
A config value is wrong on twelve lines, or you need "lines 40 to 60 of this file", or the same file without its comments. Opening an editor every time does not scale - and does not work inside a script. sed (stream editor) reads text line by line, changes it by rules you give it, and prints the result.
What you need to know already: regex basics (7.1, 7.3); sudo for files under /etc (1.11); the orders app's app.conf from 3.13.
How sed runs
sed 'SCRIPT' FILE reads FILE one line at a time, applies SCRIPT to each line, and prints every line (changed or not) to stdout. The file itself is not changed unless you ask with -i (below). The script is always in single quotes.
Substitution
s/PATTERN/REPLACEMENT/FLAGS replaces text matching the regex PATTERN:
sed 's/old/new/' the FIRST match on each line
sed 's/old/new/g' every match
sed 's/old/new/gi' ...case-insensitively
sed -E 's/([0-9]+)/[\1]/g' extended regex, with a capture group
g = global (all matches, not just the first); i = ignore case.
& in the replacement is the whole match, and \1..\9 are capture groups (the text each ( ) in the pattern matched, as in 6.10):
sed 's/^/# /' comment out every line (^ = start of line)
sed -E 's|^(/swap.img)|#\1|' comment out one specific line
The delimiter does not have to be /. s|a|b|, s#a#b#, s,a,b, all work, and using something other than / when the pattern contains paths saves you a forest of backslashes.
In place, with a backup
-i (in place) writes the result back into the file instead of printing it:
sed -i 's/old/new/g' file edit in place, no backup
sed -i.bak 's/old/new/g' file keeps the original as file.bak
Use -i.bak on anything under /etc. It costs nothing and it is the difference between "undo" and "restore from backup".
Two gotchas:
sed -ineeds write permission on the directory, not just the file - it writes a temp file and renames it. Editing a file you own in a directory you do not gives "couldn't open temporary file".- Always run without
-ifirst and read the output. There is no undo.
Addresses: which lines
An address in front of a command limits it to certain lines: a line number, a range 3,6, a regex /BEGIN/, or $ for the last line. The commands here are p (print), d (delete, i.e. do not print) and q (quit):
sed -n '3,6p' file print lines 3-6 (-n suppresses the default print)
sed -n '/BEGIN/,/END/p' file from one pattern to another
sed '1d' file delete the first line (a header)
sed '$d' file delete the last
sed '/^#/d; /^$/d' file strip comments and blank lines
sed '/pattern/s/a/b/' substitute only on matching lines
sed '10q' file quit after line 10 (like head, but stops reading)
-n plus p is the "print only what I ask for" mode, and is most of what you use sed for beyond substitution. ; separates two commands in one script.
When not to use sed
For JSON use jq (7.11). For a column of a structured log, awk (7.8) is clearer. sed is for line-oriented text substitution - and the moment your sed expression needs three layers of backslashes, you wanted a different tool.
What you can now do
- Substitute with
s///g, and edit a file in place with a backup (-i.bak). - Print a range of lines, or drop comments and blank lines.