shell · difficulty ◆◆
sed — stream editor for text transforms
Transform every line of a stream in one pass — no editor, no temp file, no fuss.
The command that looks like line noise — s/old/new/g — is the same one that rewrites configs across a thousand servers in a single line.
$ sedWhat it does
sed reads input line by line, applies the script you give it, and writes the result to stdout. It never edits the file unless you explicitly ask with -i. The core operation is the substitute command s/pattern/replacement/, but sed also deletes lines (d), prints ranges (-n '1,2p'), and filters by address. Because it reads from stdin, it slots into any pipeline: the output of grep, cat, or a log tail can be reshaped before it reaches the next tool.
Why it matters
When you need to change text across many files or a live stream, opening an editor is the wrong tool. sed does it in one non-interactive pass, which makes it scriptable and repeatable. It is the difference between hand-editing a dozen config files and running one command that fixes them all. Master the s/// idiom and the -i flag and you can rename variables, scrub secrets, or normalize logs across an entire tree in seconds.
Example
$ sed 's/x:/XX:/' passwd_sample.txtroot:XX:0:0:root:/root:/bin/bash
daemon:XX:1:1:daemon:/usr/sbin:/usr/sbin/nologin
kmail:XX:1000:1000:kmail:/home/kmail:/bin/bashSubstitute the first occurrence of 'x:' on each line with 'XX:'. The file itself is untouched — the result goes to stdout.
$ sed '/nologin/d' passwd_sample.txtroot:x:0:0:root:/root:/bin/bash
kmail:x:1000:1000:kmail:/home/kmail:/bin/bashDelete every line matching /nologin/. Addresses like /pattern/ select which lines a command acts on.
$ sed -n '1,2p' passwd_sample.txtroot:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin-n suppresses automatic printing; '1,2p' prints only lines 1 through 2. This is how you 'head' a file with sed.
$ sed -i 's/kmail/KMAIL/' passwd_edit.txtroot:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
KMAIL:x:1000:1000:kmail:/home/kmail:/bin/bash-i edits the file in place. The first 'kmail' on the last line became 'KMAIL' — the file on disk changed.
$ printf '# comment\n\nserver=8080\n\n# another\nport=3306\n' | sed '/^#/d;/^$/d'server=8080
port=3306Strip comment lines and blank lines from a config in one pass — a classic config-cleanup pipeline.
$ echo 'foo foo bar foo' | sed 's/foo/baz/g'baz baz bar bazThe g flag makes the substitution global — every 'foo' on the line, not just the first.
Common flags
- s/old/new/
- substitute the first match of 'old' with 'new' on each line
- s/old/new/g
- global — replace every match on the line, not just the first
- -n
- suppress automatic line printing; print only what you explicitly ask with p
- -i
- edit the file in place (use -i.bak to keep a backup)
- -e
- add a script expression; lets you chain multiple commands
- -E
- extended regex — so +, ?, ( ) work without backslashes
- d
- delete matching lines (e.g. /pattern/d or '1,5d')
History
Origin
sed was written by Lee E. McMahon in 1974 at Bell Labs, as a command-line version of the editing commands in the ed text editor. The name is short for 'stream editor'. Where ed was interactive, sed was designed to run non-interactively over a stream — which is exactly what made it scriptable and why it survived while ed faded.
The s/// legacy
The substitute syntax s/pattern/replacement/ that sed popularized became so universal that Perl, awk, and even modern editors all borrowed it. When you type :%s/foo/bar/g in vim, you are using sed's grammar. GNU sed 4.9, the version on most Linux boxes, still runs the same core language McMahon designed in 1974.
Fun facts
Pros & cons
pros
- + Non-interactive and scriptable — the same transform runs on one file or a thousand
- + Streams from stdin, so it composes with every other Unix filter
- + In-place editing (-i) makes bulk config changes a one-liner
cons
- − The terse syntax is hard to read at a glance — s/old/new/g looks like line noise until you know it
- − Line-oriented: it struggles with edits that span multiple lines
- − Regex escaping rules differ between basic and extended mode, a classic source of confusion
Takeaways
- 1s/old/new/ replaces the first match per line; add g to replace every match
- 2Use -n with p to print only selected lines — sed's version of head
- 3Back up with -i.bak before editing files in place
- 4Chain commands with -e or semicolons: sed -e 's/a/b/' -e '/^#/d'
- 5Reach for -E for extended regex so +, ?, and ( ) work without backslashes