sed
Overview
sed (stream editor) transforms text line by line — substitute, delete, print, and simple inserts — without opening an interactive editor. GNU sed is standard on Ubuntu/Debian. Prefer sed for mechanical rewrites; use awk for field logic and an editor for multi-line structural edits.
Syntax
sed [options] 'script' [file...]
sed [options] -e 'script' -e 'script' [file...]
sed [options] -f script.sed [file...]
… | sed 'script'Common Options
| Option | Description |
|---|---|
-n |
Quiet; only explicit p prints |
-E / -r |
Extended regex (ERE) |
-i[SUFFIX] |
In-place edit (optional backup suffix) |
-e |
Add a script expression |
-f file |
Read script from file |
-z |
NUL-separated “lines” (GNU; useful with find -print0) |
Common script commands
| Cmd | Meaning |
|---|---|
s/pat/repl/flags |
Substitute (g global, i ignore case, p print, 2 Nth only) |
d |
Delete line |
p |
Print line |
a\ / i\ / c\ |
Append / insert / change (multi-line form in scripts) |
q / Q |
Quit (GNU Q without printing pattern space) |
y/src/dst/ |
Transliterate like tr |
= |
Print line number |
Safety
sed -irewrites files — always keep backups (-i.bak) until the expression is trusted.
- Prefer single quotes around scripts so the shell does not expand
$and`.
- Never run
sed -ion binary files or unknown encodings.
- On macOS,
-irequires a mandatory suffix argument — scripts written for GNU sed may break there.
Key Use Cases
- Bulk string replace in config/logs
- Strip comments/blank lines
- Extract a capture group (print-only substitute)
- Normalize line endings / trailing whitespace
- Quick in-place flips for feature flags
Examples with Explanations
Substitute first match per line
sed 's/foo/bar/' file.txtOnly the first foo on each line becomes bar.
Global substitute
sed 's/foo/bar/g' file.txtEvery non-overlapping match on the line is replaced.
Extended regex
sed -E 's/[0-9]{1,3}(\.[0-9]{1,3}){3}/IP/g' access.logWith -E, {} and () work without backslashes (GNU ERE).
Delete matching lines
sed '/^#/d; /^$/d' config.txtDrops comment lines and empty lines — useful for “effective config” views.
Print only rewritten matches
sed -n 's/.*ERROR: //p' app.log-n suppresses default output; p prints only successful substitutions — like a capturing grep.
In-place with backup
sed -i.bak 's/Enable=false/Enable=true/' app.conf
diff -u app.conf.bak app.confInspect the diff before deleting the .bak.
Line addresses and ranges
sed -n '10,20p' file.txt # print lines 10–20
sed '1,5d' file.txt # delete first five
sed '/^## Start/,/^## End/d' doc.mdAddresses can be numbers, $ (last line), or /regex/.
Multiple expressions
sed -e 's/\r$//' -e 's/[[:space:]]\+$//' file.txtStrip CR from CRLF files and trailing whitespace.
Use match in replacement
sed -E 's/(user=)[^ ]+/\1REDACTED/g' app.logParentheses capture; \1 reinserts the prefix. & is the whole match.
Change delimiter when paths have slashes
sed 's|/usr/local/bin|/opt/bin|g' env.shAny character after s can be the delimiter (s|||, s###).
Hold space: join two lines (advanced)
sed -n '1h;1!H;${x;s/\n/,/g;p}' list.txtGNU sed can join lines via hold space; for heavy multi-line work prefer awk or perl.
Dry-run pattern for risky edits
sed 's/prod/staging/g' settings.yml | diff -u settings.yml -
# then:
sed -i.bak 's/prod/staging/g' settings.ymlAlways preview against the original before -i.
Understanding Output
By default sed prints every line (after script processing) to stdout. Exit status is 0 on success; GNU sed can return non-zero for invalid options or I/O errors. In-place mode still writes a temporary file then renames — a full disk mid-edit can fail; keep backups.
Notes & Pitfalls
- Default regex is BRE;
+,?,|need escapes unless you use-E.
s/a/b/only changes the first match; forgetgoften.
&in the replacement is the whole match; write\&for a literal ampersand.
sedis line-oriented — multi-line HTML/XML edits are painful.
- Character classes: prefer
[[:space:]]over\sfor portable scripts.
Additional Resources
man sed
- GNU sed manual