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...)                           │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

Essential Commands

Command Meaning Example

s

Substitute

s/old/new/

d

Delete line

/pattern/d

p

Print line

/pattern/p

a

Append after

a\new line

i

Insert before

i\new line

c

Change/replace line

c\replacement

y

Transliterate

y/abc/xyz/

q

Quit

10q


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"

Special Replacements

# & represents the matched string
sed 's/[0-9]\+/(&)/g' file.txt
# "line 42" → "line (42)"

# Uppercase matched text
sed 's/[a-z]\+/\U&/g' file.txt

# Lowercase matched text
sed 's/[A-Z]\+/\L&/g' file.txt

# Capitalize first letter
sed 's/[a-z]/\u&/' file.txt

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

Combined Addresses

# Pattern + offset
sed -n '/START/,+5p' file.txt  # START plus next 5 lines

# Negation
sed -n '/pattern/!p' file.txt  # lines NOT matching

# Multiple patterns
sed -n '/pattern1/p; /pattern2/p' 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

Replace Entire Lines

# Replace line matching pattern
sed '/pattern/c\Replacement line' file.txt

# Replace line 5
sed '5c\New line 5' file.txt

Multi-Line Operations

Join Lines

# Join every pair of lines
sed 'N;s/\n/ /' file.txt

# Join continuation lines (ending with \)
sed ':a; /\\$/N; s/\\\n//; ta' file.txt

# Join all lines into one
sed ':a;N;$!ba;s/\n/ /g' file.txt

Multi-Line Patterns

# Delete block between patterns (inclusive)
sed '/START/,/END/d' file.txt

# Keep only blocks between patterns
sed -n '/START/,/END/p' file.txt

# Replace multi-line pattern
sed -n 'H;${x;s/pattern1.*pattern2/replacement/;p}' file.txt

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

Systemd Units

# Update ExecStart
sed -i 's|^ExecStart=.*|ExecStart=/usr/bin/newcommand --flag|' /etc/systemd/system/myservice.service

# Add After dependency
sed -i '/^\[Unit\]/a After=network-online.target' myservice.service

Certificate Files

# Remove Windows line endings
sed -i 's/\r$//' certificate.pem

# Extract between markers
sed -n '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/p' fullchain.pem

# Remove blank lines between certs
sed -i '/^$/d' chain.pem

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

Multiple Operations

# Multiple substitutions
sed 's/foo/bar/g; s/baz/qux/g' file.txt

# Or with -e
sed -e 's/foo/bar/g' -e 's/baz/qux/g' file.txt

# From file
cat > changes.sed << 'EOF'
s/old1/new1/g
s/old2/new2/g
/delete_me/d
EOF
sed -f changes.sed input.txt

In-Place Editing Safety

Always Verify First

# Preview changes (no -i)
sed 's/old/new/g' config.ini

# Verify specific line BEFORE change
sed -n '73p' /etc/ssh/sshd_config

# Make change
sed -i '73s/old/new/' /etc/ssh/sshd_config

# Verify AFTER change
sed -n '73p' /etc/ssh/sshd_config

Backup Strategy

# In-place with backup
sed -i.bak 's/old/new/g' config.ini

# Timestamped backup
sed -i.$(date +%Y%m%d) 's/old/new/g' config.ini

# Backup to directory
cp config.ini /backup/config.ini.$(date +%s)
sed -i 's/old/new/g' config.ini

Quick Reference

Task Command

Replace first occurrence

sed 's/old/new/'

Replace all occurrences

sed 's/old/new/g'

In-place edit

sed -i 's/old/new/g' file

Delete lines matching

sed '/pattern/d'

Print lines matching

sed -n '/pattern/p'

Delete line N

sed 'Nd'

Print line N

sed -n 'Np'

Delete blank lines

sed '/^$/d'

Insert before line

sed 'Ni\text'

Append after line

sed 'Na\text'

Replace line N

sed 'Nc\new text'

Delete range

sed '5,10d'

Use different delimiter

sed 's|/old|/new|g'

Capture groups

sed 's/\(a\)\(b\)/\2\1/'

Extended regex

sed -E 's/(a)(b)/\2\1/'

Multiple commands

sed 's/a/b/; s/c/d/'

From script file

sed -f script.sed


sed vs awk vs Other Tools

Task Use sed Use awk instead

Simple substitution

sed 's/old/new/g'

Overkill

Conditional substitution

Complex

awk '/cond/ {gsub(); print}'

Column extraction

Possible but awkward

awk '{print $3}'

Line deletion by pattern

sed '/pattern/d'

awk '!/pattern/'

Math on values

Not possible

awk '{print $1 * 2}'

Aggregation

Not possible

awk '{sum+=$1} END {print sum}'

Rule of thumb: sed for substitutions and line operations, awk for field processing and logic.