sed
sed (stream editor) transforms text as it flows through. Master substitution, line addressing, and the hold buffer for powerful text manipulation.
Basic Syntax
sed [options] 'command' file
sed [options] -e 'cmd1' -e 'cmd2' file
sed [options] -f script.sed file
Substitution (s)
Basic Replace
sed 's/old/new/' file # First occurrence per line
sed 's/old/new/g' file # All occurrences (global)
sed 's/old/new/2' file # Second occurrence only
sed 's/old/new/gi' file # Global, case insensitive
Delimiters
Any character can be a delimiter:
sed 's/path/to/new\/path/' file # Escaping / is ugly
sed 's|path/to|new/path|g' file # Use | instead
sed 's#path/to#new/path#g' file # Or #
Regex in Substitution
# Match any digit
sed 's/[0-9]/#/g' file
# Capture groups
sed 's/\(.*\)@\(.*\)/User: \1, Domain: \2/' file
# Extended regex (-E)
sed -E 's/([a-z]+)@([a-z.]+)/User: \1, Domain: \2/' file
Backreferences
# Duplicate word
sed 's/\(word\)/\1 \1/' file
# Swap fields
sed -E 's/([^,]+),([^,]+)/\2,\1/' file
# Use & for entire match
sed 's/[0-9]*/(&)/' file # Wrap number in parens
In-Place Editing
# Edit file directly
sed -i 's/old/new/g' file
# With backup
sed -i.bak 's/old/new/g' file # Creates file.bak
-i is destructive. Test without it first.
|
Line Addressing
By Line Number
sed '5s/old/new/' file # Only line 5
sed '1,10s/old/new/g' file # Lines 1-10
sed '5,$s/old/new/g' file # Line 5 to end
By Pattern
sed '/error/s/old/new/' file # Lines containing "error"
sed '/start/,/end/s/a/b/g' file # Between patterns
Step Addressing
sed '1~2s/old/new/' file # Odd lines (1, 3, 5...)
sed '0~2s/old/new/' file # Even lines (2, 4, 6...)
Print (p)
# Print lines (with -n to suppress default output)
sed -n '5p' file # Line 5 only
sed -n '10,20p' file # Lines 10-20
sed -n '/pattern/p' file # Lines matching pattern
sed -n '1p;$p' file # First and last line
Delete (d)
sed '5d' file # Delete line 5
sed '/^$/d' file # Delete empty lines
sed '/^#/d' file # Delete comments
sed '1,10d' file # Delete first 10 lines
sed '/start/,/end/d' file # Delete range
Insert/Append/Change
Insert Before (i)
sed '3i\New line here' file # Insert before line 3
sed '/pattern/i\New line' file # Insert before matching lines
Append After (a)
sed '3a\New line here' file # Append after line 3
sed '$a\Last line' file # Append at end
Change Line (c)
sed '5c\Replacement line' file # Replace line 5
sed '/old/c\new line' file # Replace matching lines
Multiple Commands
With -e
sed -e 's/a/A/' -e 's/b/B/' file
With Semicolon
sed 's/a/A/; s/b/B/' file
With Script File
cat << 'EOF' > script.sed
s/old/new/g
/comment/d
1i\Header line
EOF
sed -f script.sed file
With Braces (Address Block)
sed '/start/,/end/{
s/a/A/g
s/b/B/g
}' file
Hold Buffer (Advanced)
sed has two buffers: - Pattern space: Current line being processed - Hold space: Auxiliary storage
Commands
| Command | Action |
|---|---|
h |
Copy pattern space to hold space |
H |
Append pattern space to hold space |
g |
Copy hold space to pattern space |
G |
Append hold space to pattern space |
x |
Exchange pattern and hold space |
Example: Reverse Lines
sed '1!G;h;$!d' file
Example: Join Lines
# Join every two lines
sed 'N;s/\n/ /' file
Example: Print Paragraph Containing Pattern
sed -n '/pattern/{
:loop
N
/\n$/!b loop
p
}' file
Next Line (n/N)
# n: Replace pattern space with next line
sed '/pattern/{n;d}' file # Delete line after pattern
# N: Append next line to pattern space
sed 'N;s/\n/ /' file # Join pairs of lines
Quit (q)
sed '10q' file # Quit after line 10 (like head)
sed '/pattern/q' file # Quit at first match
Infrastructure Patterns
Remove Comments and Blank Lines
sed '/^#/d; /^$/d' config.conf
# Or combined
sed '/^#\|^$/d' config.conf
Extract Value from Config
sed -n 's/^DB_HOST=//p' .env
Update Config Value
sed -i 's/^DB_HOST=.*/DB_HOST=newhost/' .env
Add Line After Match
sed '/\[section\]/a\new_key=value' config.ini
Replace IP Address
sed -i 's/192\.168\.1\.1/10.0.0.1/g' hosts
Normalize Whitespace
# Multiple spaces to single
sed 's/ */ /g' file
# Trim leading whitespace
sed 's/^[[:space:]]*//' file
# Trim trailing whitespace
sed 's/[[:space:]]*$//' file
# Trim both
sed 's/^[[:space:]]*//;s/[[:space:]]*$//' file
Fix Line Endings
# DOS to Unix
sed 's/\r$//' file
# Unix to DOS
sed 's/$/'$'\r'/ file
Extract Between Delimiters
sed -n '/<config>/,/<\/config>/p' file
Number Lines
sed = file | sed 'N;s/\n/\t/'
Print Specific Line
sed -n '42p' file # Line 42
sed -n '42{p;q}' file # Line 42, then quit (faster)
Replace in Specific Lines
# Only in lines containing pattern
sed '/VLAN/s/10/20/g' config
# Lines 50-100
sed '50,100s/old/new/g' file
Combining with Other Tools
grep → sed
grep -l "pattern" *.conf | xargs sed -i 's/old/new/g'
sed → awk
sed 's/,/ /g' file.csv | awk '{print $2}'
find → sed
find . -name "*.conf" -exec sed -i 's/old/new/g' {} \;
Common Mistakes
Forgetting -i Backup
# WRONG: No recovery if mistake
sed -i 's/critical/wrong/g' important.conf
# RIGHT: Keep backup
sed -i.bak 's/critical/wrong/g' important.conf
Escaping
# WRONG: Unescaped special chars
sed 's/*.log/.txt/' file
# RIGHT: Escape metacharacters
sed 's/\*.log/.txt/' file
Greedy Matching
# WRONG: Too greedy
echo "<a>text</a>" | sed 's/<.*>/X/' # X
# RIGHT: Non-greedy workaround
echo "<a>text</a>" | sed 's/<[^>]*>/X/g' # XtextX
Quick Reference
# Commands
s/old/new/g # Substitute
d # Delete line
p # Print line
i\text # Insert before
a\text # Append after
c\text # Change line
q # Quit
# Flags
-n # Suppress auto-print
-i # In-place edit
-i.bak # In-place with backup
-E # Extended regex
-e # Multiple commands
-f # Script file
# Addresses
5 # Line 5
5,10 # Lines 5-10
$ # Last line
/pattern/ # Matching lines
/start/,/end/ # Range by pattern
Key Takeaways
-
s/old/new/g- g for global (all occurrences) -
-i.bak- Always backup with in-place -
Alternative delimiters - Use
|or#with paths -
-nwithp- Suppress default, print specific -
Addresses - Control which lines are affected
-
-E- Extended regex for modern syntax -
Test first - Run without
-ito verify
Next Module
awk - Field processing and text manipulation.