sed: Stream Editor for Replacing and Transforming Text
sed reads text line-by-line and applies an editing command to each. Most people use it for one thing: search and replace. But sed can also delete lines, print specific ranges, transform formats, and edit files in place. The syntax is dense; learning the 10 most useful patterns covers 95% of real use.
The basic substitute command
# Replace first occurrence of "foo" with "bar" on each line
sed 's/foo/bar/' file.txt
# Replace ALL occurrences (g flag = global)
sed 's/foo/bar/g' file.txt
# Case-insensitive
sed 's/foo/bar/gi' file.txt
The default sends output to stdout — the file is NOT modified. That’s a feature: pipe through sed without risking your data.
Edit a file in place
sed -i 's/foo/bar/g' file.txt # WRITES to file
sed -i.bak 's/foo/bar/g' file.txt # makes file.txt.bak first
Always use -i.bak for important files. If sed messes up, you have a backup.
Use any delimiter (not just /)
If your pattern has slashes (paths, URLs), use a different delimiter:
sed 's|/old/path|/new/path|g' config.conf
sed 's#http://#https://#g' urls.txt
Address ranges: edit specific lines
sed '5s/foo/bar/' file # only line 5
sed '1,10s/foo/bar/g' file # lines 1-10
sed '/start/,/end/s/foo/bar/g' file # between matching lines
sed '$s/foo/bar/' file # only last line
sed '/^#/d' file # delete comment lines
sed '/^$/d' file # delete blank lines
Print specific lines
# By default sed prints every line. -n suppresses; p prints matched ones.
sed -n '5p' file # only line 5
sed -n '5,10p' file # lines 5-10
sed -n '/error/p' file # only lines containing "error"
sed -n '$p' file # last line
Multiple commands
# Chain with -e
sed -e 's/foo/bar/g' -e 's/baz/qux/g' file
# Or use semicolons
sed 's/foo/bar/g; s/baz/qux/g' file
# Or a script file
sed -f script.sed file
Real-world one-liners
# Remove trailing whitespace from every line
sed -i 's/[[:space:]]*$//' file
# Remove leading whitespace
sed -i 's/^[[:space:]]*//' file
# Convert Windows line endings to Unix
sed -i 's/r$//' file.txt
# Replace in many files at once
sed -i 's/old_company/new_company/g' *.txt
# Comment out a line in a config file
sed -i 's/^DEBUG=true/#DEBUG=true/' app.conf
# Uncomment a line
sed -i 's/^#(LoadModule rewrite_module)/1/' httpd.conf
# Print only lines 100 through 200 of a huge file
sed -n '100,200p' bigfile.log
# Insert a line BEFORE line 5
sed '5i
This is a new line' file
# Append a line AFTER line 5
sed '5a
This is a new line' file
Capture groups (substitution)
Parentheses in BRE need backslashes: (...). Refer to captures with 1, 2, etc.
# Swap "first last" to "last, first"
echo "Linus Torvalds" | sed 's/([^ ]*) (.*)/2, 1/'
# → Torvalds, Linus
# Use -E (extended regex) to skip the backslashes
echo "Linus Torvalds" | sed -E 's/([^ ]+) (.+)/2, 1/'
Common mistakes
- Forgetting
g— only replaces first occurrence per line. - Forgetting to quote — bash interprets
$,!,*before sed sees them. Use single quotes. - Editing without backup with
-ion irreplaceable files. Always-i.bak. - Using slashes in patterns. Switch to
|or#for path/URL replacement.
What to learn next
sed handles substitution. awk handles columns and structured text. Together they’re the backbone of shell text processing — awk is up next.