SED (Stream Editor) is the specialist tool for text substitution and transformation in shell pipelines. While AWK is a programming language that happens to process text, SED is a pure transformation engine — it applies a script of commands to each line of input and outputs the result. Understanding SED deeply makes you faster at config file editing, log transformation, and in-place file updates.
1
SED execution model and pattern space
BASH
# SED cycle (repeated for each input line):
# 1. Read line into pattern space
# 2. Apply commands in sequence to pattern space
# 3. Print pattern space (unless -n)
# 4. Clear pattern space and go to next line
# ── Basic invocation ──────────────────────────────────────
sed 'COMMAND' file.txt # apply to file
echo "text" | sed 'COMMAND' # apply to stdin
sed -n 'COMMAND' file.txt # -n: suppress auto-print
sed -i 'COMMAND' file.txt # -i: edit file in place (GNU sed)
sed -i.bak 'COMMAND' file.txt # -i.bak: in-place with backup
sed -E 'COMMAND' file.txt # -E: extended regex (no backslash)
# ── Multiple commands ─────────────────────────────────────
sed '/ERROR/d; s/WARN/WARNING/' file.txt # semicolon separator
sed -e '/ERROR/d' -e 's/WARN/WARNING/' # multiple -e flags
sed '
/ERROR/d
s/WARN/WARNING/
' file.txt # multiline string
# ── GNU sed vs BSD sed (macOS) ─────────────────────────────
# GNU sed: sed -i 's/old/new/' file (no space needed)
# BSD sed: sed -i '' 's/old/new/' file (empty string required)
# Safe cross-platform in-place edit:
if [[ "$(uname)" == "Darwin" ]]; then
sed -i '' 's/old/new/g' file.txt
else
sed -i 's/old/new/g' file.txt
fi
2
Primary SED commands
SED
# ── s — substitute (most used) ────────────────────────────
sed 's/old/new/' # replace first occurrence per line
sed 's/old/new/g' # replace all occurrences (global)
sed 's/old/new/2' # replace second occurrence only
sed 's/old/new/i' # case-insensitive (GNU sed)
sed 's/old/new/gp' # replace all + print if changed
# ── d — delete line ────────────────────────────────────────
sed '/pattern/d' # delete lines matching pattern
sed '/^#/d' # delete comment lines
sed '/^[[:space:]]*$/d' # delete blank lines
sed '1d' # delete first line
sed '$d' # delete last line
sed '2,5d' # delete lines 2 through 5
# ── p — print ─────────────────────────────────────────────
sed -n '/ERROR/p' # print only lines matching ERROR
sed -n '5p' # print only line 5
sed -n '5,10p' # print lines 5-10
sed -n '$p' # print last line
# ── q — quit ──────────────────────────────────────────────
sed '5q' # print first 5 lines and quit (like head -5)
sed '/ERROR/q' # print up to and including first ERROR
# ── a, i, c — append, insert, change ─────────────────────
sed '/pattern/a\Added after' # append line after match
sed '/pattern/i\Added before' # insert line before match
sed '/pattern/c\Replaced line' # replace entire line
# ── y — transliterate ─────────────────────────────────────
sed 'y/abc/ABC/' # a→A, b→B, c→C (like tr)
sed 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' # uppercase
3
Address forms — targeting specific lines
BASH
# SED address: [address] command
# Address specifies WHICH lines the command applies to
# ── Numeric addresses ─────────────────────────────────────
sed '1s/old/new/' # only first line
sed '$s/old/new/' # only last line
sed '2,5s/old/new/' # lines 2 through 5
sed '2,~5s/old/new/' # line 2 through next mult of 5 (GNU)
sed '0~2s/old/new/' # every 2nd line starting at 0 (GNU)
sed '1~2s/old/new/' # every odd line (GNU)
# ── Regex addresses ───────────────────────────────────────
sed '/ERROR/s/old/new/' # only on ERROR lines
sed '/^#/d' # delete comment lines
# ── Range addresses ───────────────────────────────────────
sed '/START/,/END/s/old/new/' # between START and END
sed '/START/,/END/d' # delete block between START and END
sed '1,/PATTERN/d' # delete from line 1 to first PATTERN
sed '/PATTERN/,$d' # delete from PATTERN to end of file
# ── Negated address (!) ────────────────────────────────────
sed '/ERROR/!d' # delete lines NOT matching ERROR
sed '1!s/old/new/' # substitute on all but first line
vriddh@prod-01:~/scripts$echo "Hello World Error" | sed 's/Error/Fixed/'
Hello World Fixed
vriddh@prod-01:~/scripts$sed '/^#/d; /^[[:space:]]*$/d' config.conf | head -5
DB_HOST=prod-db-01
DB_PORT=3306
APP_ENV=production
vriddh@prod-01:~/scripts$sed -n '5,10p' app.log
[2026-05-01 10:14:05] INFO Service started
[2026-05-01 10:14:06] ERROR DB connection failed
█
⚠ GNU sed vs BSD sed (macOS) — The most common cross-platform breakage:
sed -i 's/old/new/' file works on GNU/Linux but fails on macOS BSD sed. On macOS you need sed -i '' 's/old/new/' file. For scripts that must run on both, detect the platform or install GNU sed via Homebrew (brew install gnu-sed provides gsed).✔ SED fundamentals —
s/pattern/replacement/flags is the core. Use g for global, I for case-insensitive (GNU). Use -n with p to print only matched lines. Use -i for in-place editing — always with .bak suffix until you trust the expression. Use -E for extended regex to avoid backslashing +, ?, (), and |.