sed: Stream Editor
sed transforms text streams. It’s the surgeon’s scalpel for config files and log processing.
Core Concepts
The sed Model
┌─────────────────────────────────────────────────────────────────┐
│ SED PROCESSING MODEL │
├─────────────────────────────────────────────────────────────────┤
│ │
│ INPUT ADDRESS + COMMAND OUTPUT │
│ ───── ───────────────── ────── │
│ │
│ line 1 ──► [address]command ──► modified line │
│ line 2 ──► s/old/new/ ──► modified line │
│ line 3 ──► /pattern/d ──► (deleted) │
│ ... 5,10p ──► (lines 5-10 printed) │
│ │
│ ADDRESSES (which lines to affect) │
│ ───────── │
│ 5 - line 5 │
│ 5,10 - lines 5 through 10 │
│ /pattern/ - lines matching regex │
│ $ - last line │
│ 1~2 - odd lines (1, 3, 5...) │
│ │
└─────────────────────────────────────────────────────────────────┘
Substitution
Basic Substitution
# Replace first occurrence
sed 's/old/new/' file.txt
# Replace all occurrences (global)
sed 's/old/new/g' file.txt
# Replace Nth occurrence
sed 's/old/new/2' file.txt
# Case insensitive
sed 's/old/new/gi' file.txt
# In-place editing
sed -i 's/old/new/g' file.txt
# In-place with backup
sed -i.bak 's/old/new/g' file.txt
Delimiters
# Default delimiter (/)
sed 's/path\/to\/file/new\/path/' file.txt
# Alternative delimiter (cleaner for paths)
sed 's|/path/to/file|/new/path|g' file.txt
sed 's#/path/to/file#/new/path#g' file.txt
sed 's@/path/to/file@/new/path@g' file.txt
Capture Groups
# Backreference with \1
sed 's/\(hello\) \(world\)/\2 \1/' file.txt
# "hello world" → "world hello"
# Extended regex (-E or -r) for cleaner syntax
sed -E 's/(hello) (world)/\2 \1/' file.txt
# Surround matches
sed 's/[0-9]\+/[&]/g' file.txt
# "line 42 here" → "line [42] here"
# Extract and reformat
sed -E 's/([0-9]{4})-([0-9]{2})-([0-9]{2})/\2\/\3\/\1/g' file.txt
# "2026-02-26" → "02/26/2026"
Line Selection (Addressing)
Line Numbers
# Specific line
sed -n '5p' file.txt
# Line range
sed -n '5,10p' file.txt
# From line 5 to end
sed -n '5,$p' file.txt
# Last line
sed -n '$p' file.txt
# Every other line (odd)
sed -n '1~2p' file.txt
# Every other line (even)
sed -n '2~2p' file.txt
# First 10 lines
sed -n '1,10p' file.txt
# Skip first line
sed '1d' file.txt
Pattern Addresses
# Lines matching pattern
sed -n '/ERROR/p' file.txt
# Lines NOT matching
sed '/DEBUG/d' file.txt
# Range between patterns
sed -n '/START/,/END/p' file.txt
# Substitute only on matching lines
sed '/ERROR/s/warning/critical/' file.txt
# Delete from pattern to end
sed '/STOP/,$d' file.txt
Line Operations
Delete Lines
# Delete line 5
sed '5d' file.txt
# Delete range
sed '5,10d' file.txt
# Delete matching lines
sed '/pattern/d' file.txt
# Delete blank lines
sed '/^$/d' file.txt
# Delete lines with only whitespace
sed '/^[[:space:]]*$/d' file.txt
# Delete first line
sed '1d' file.txt
# Delete last line
sed '$d' file.txt
# Delete lines starting with #
sed '/^#/d' file.txt
Insert and Append
# Insert before line 5
sed '5i\New line here' file.txt
# Append after line 5
sed '5a\New line here' file.txt
# Insert before pattern
sed '/pattern/i\New line before' file.txt
# Append after pattern
sed '/pattern/a\New line after' file.txt
# Insert at beginning
sed '1i\First line' file.txt
# Append at end
sed '$a\Last line' file.txt
# Multiple lines (GNU sed)
sed '/pattern/a\
line 1\
line 2\
line 3' file.txt
Multi-Line Operations
Infrastructure Automation
Config File Modifications
# Change config value
sed -i 's/^hostname=.*/hostname=newhost/' config.ini
# Uncomment a line
sed -i 's/^#\(setting=value\)/\1/' config.ini
# Comment a line
sed -i 's/^\(setting=value\)/#\1/' config.ini
# Update specific key-value
sed -i '/^database_host/s/=.*/=newdb.example.com/' config.ini
# Add line after pattern (if not exists)
grep -q 'new_setting' config.ini || sed -i '/\[section\]/a new_setting=value' config.ini
SSH Config
# Update PermitRootLogin
sed -i 's/^#*PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config
# Enable password auth
sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config
# Change specific line by number (after verification)
sed -i '73s/.*/GSSAPIAuthentication yes/' /etc/ssh/sshd_config
Network Configuration
# Update IP address in netplan
sed -i 's/192.168.1.100/10.50.1.100/g' /etc/netplan/01-config.yaml
# Update DNS in resolv.conf
sed -i 's/^nameserver.*/nameserver 10.50.1.90/' /etc/resolv.conf
# Change hostname
sed -i "s/$(hostname)/newhostname/g" /etc/hostname /etc/hosts
Practical Patterns
Log Processing
# Remove timestamps (first 20 chars)
sed 's/^.\{20\}//' app.log
# Extract between brackets
sed 's/.*\[\([^]]*\)\].*/\1/' app.log
# Anonymize IP addresses
sed -E 's/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/X.X.X.X/g' access.log
# Remove ANSI color codes
sed 's/\x1b\[[0-9;]*m//g' colored.log
Data Transformation
# CSV to TSV
sed 's/,/\t/g' data.csv
# Trim whitespace
sed 's/^[[:space:]]*//;s/[[:space:]]*$//' file.txt
# Normalize multiple spaces
sed 's/ */ /g' file.txt
# Remove leading zeros
sed 's/^0*//' numbers.txt
# Add prefix to each line
sed 's/^/PREFIX: /' file.txt
# Add suffix to each line
sed 's/$/ SUFFIX/' file.txt
In-Place Editing Safety
Quick Reference
| Task | Command |
|---|---|
Replace first occurrence |
|
Replace all occurrences |
|
In-place edit |
|
Delete lines matching |
|
Print lines matching |
|
Delete line N |
|
Print line N |
|
Delete blank lines |
|
Insert before line |
|
Append after line |
|
Replace line N |
|
Delete range |
|
Use different delimiter |
|
Capture groups |
|
Extended regex |
|
Multiple commands |
|
From script file |
|
sed vs awk vs Other Tools
| Task | Use sed | Use awk instead |
|---|---|---|
Simple substitution |
|
Overkill |
Conditional substitution |
Complex |
|
Column extraction |
Possible but awkward |
|
Line deletion by pattern |
|
|
Math on values |
Not possible |
|
Aggregation |
Not possible |
|
Rule of thumb: sed for substitutions and line operations, awk for field processing and logic.
Related
-
awk - When you need column processing
-
Shell Pipelines - Combining tools