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

  1. s/old/new/g - g for global (all occurrences)

  2. -i.bak - Always backup with in-place

  3. Alternative delimiters - Use | or # with paths

  4. -n with p - Suppress default, print specific

  5. Addresses - Control which lines are affected

  6. -E - Extended regex for modern syntax

  7. Test first - Run without -i to verify

Next Module

awk - Field processing and text manipulation.