sed in ten minutes

general / published / guide #20 / ≈ 4 min read

sed is the stream editor. It reads a file (or piped input) line by line, applies transformations you specify, and writes the result to standard output. It's like running a tiny find-and-replace through your file from the command line, without ever opening an editor.

You'll see sed most often in three contexts: quick text substitutions, scripted edits to config files, and the occasional log-munging pipeline. This guide covers exactly that.

The classic: substitute

sed 's/old/new/' file.txt

Reads file.txt, replaces the first occurrence of "old" with "new" on each line, prints the result. Doesn't change the original file.

The s command structure is s/pattern/replacement/flags. Common flags:

  • g — replace all occurrences on each line, not just the first
  • i — case-insensitive match
  • 3 — replace only the third match on each line
sed 's/old/new/g' file.txt        # all occurrences per line
sed 's/CAT/dog/gi' file.txt        # any case of "cat" → "dog"

Edit a file in place (-i)

To modify the file directly instead of just printing:

sed -i 's/old/new/g' file.txt              # Linux (GNU sed)
sed -i '' 's/old/new/g' file.txt          # BSD / macOS — empty backup suffix
sed -i.bak 's/old/new/g' file.txt          # keep a backup as file.txt.bak

Heads up: the -i flag is one of the few places sed differs between GNU (Linux) and BSD (FreeBSD/macOS). On BSD you must give it an argument — an empty string '' means "no backup."

Different separator (when your text contains slashes)

The first character after s is the separator. Use any character that's not in your strings:

# classic problem: paths contain slashes
sed 's|/usr/local/|/opt/|g' config.txt
sed 's#http://#https://#' urls.txt

Delete lines

sed '/pattern/d' file.txt          # delete lines matching pattern
sed '/^$/d' file.txt                # delete blank lines
sed '/^#/d' file.txt                # delete comment lines
sed '1d' file.txt                   # delete the first line (e.g., CSV header)
sed '$d' file.txt                   # delete the last line
sed '1,10d' file.txt                # delete lines 1 to 10

Print only matching lines (-n + /p)

By default sed prints every line. The -n flag silences that, then you tell it explicitly what to print:

# works like grep
sed -n '/error/p' /var/log/syslog

# print only lines 10–20
sed -n '10,20p' file.txt

# print from line 10 to the end of the file ($ = the last line)
sed -n '10,$p' file.txt

Address ranges — work on a slice of the file

Most commands accept an "address" telling sed which lines to act on:

sed '1,5s/foo/bar/g' file.txt              # only on lines 1–5
sed '/BEGIN/,/END/s/foo/bar/g' file.txt   # between the BEGIN and END markers
sed '10,$d' file.txt                       # delete from line 10 to the end

This is one of sed's superpowers — you can scope an edit precisely. The pattern /BEGIN/,/END/ is especially handy for editing config blocks bounded by markers.

Multiple commands in one pass

Use -e or a semicolon:

sed -e 's/foo/bar/g' -e 's/baz/qux/g' file.txt
sed 's/foo/bar/g; s/baz/qux/g' file.txt

For more complex edits, write a sed script file:

# tidy.sed
/^#/d
/^$/d
s/[[:space:]]\+$//
s/[[:space:]]\+/ /g

Run it with:

sed -f tidy.sed input.txt

That tiny script strips comments, blank lines, trailing whitespace, and collapses runs of internal whitespace — useful for cleaning up someone else's config file.

Capture groups for restructuring

Use \1, \2, etc. in the replacement to refer back to parts of the match. The pattern uses \( ... \) to capture (or ( ... ) with the -E flag for extended regex):

# swap the order of "first last" to "last, first"
echo "Ada Lovelace" | sed -E 's/(\S+) (\S+)/\2, \1/'
# Lovelace, Ada

# capture a port out of a URL
echo "http://example.com:8080/path" | sed -E 's|.*:([0-9]+)/.*|\1|'
# 8080

Real-world examples

# strip Windows-style carriage returns from a file
sed -i 's/\r$//' file.txt

# uncomment a setting in a config file
sed -i 's/^#\(Port .*\)/\1/' /etc/ssh/sshd_config

# change a value in a config file
sudo sed -i 's/^Port .*/Port 2222/' /etc/ssh/sshd_config

# extract just the lines between two markers
sed -n '/^BEGIN/,/^END/p' config.txt

# add a line after every match
sed '/^Section/a\
new line here' file.txt

The shortest summary

  • sed 's/old/new/g' — replace all "old" with "new" on every line.
  • -i — edit the file in place. -i.bak to keep a backup.
  • /pattern/d — delete matching lines.
  • -n '/pattern/p' — print only matching lines (sed as grep).
  • Address ranges like 1,10 or /BEGIN/,/END/ scope edits.
  • Combine multiple edits with -e or a script file.

Combined with awk and the basic pipe vocabulary, you'll handle the great majority of "I need to transform a text file" tasks without ever writing a real program.

← back to index