sed vs awk: When to Use Each One
sed edits lines; awk understands columns. Substitution is sed, computation is awk.
Side by side
| sed | awk | |
|---|---|---|
| Mental model | Stream editor, one line at a time | Columns and records, like a tiny spreadsheet |
| Substitution | Its whole purpose (s/old/new/g) | Possible (sub, gsub) but clumsier |
| Field access | Not really | Native: $1, $2, $NF |
| Arithmetic | No | Yes — sums, averages, counters |
| Variables and arrays | Very limited | Full associative arrays |
| Edit files in place | Yes (-i) | Only with -i inplace (GNU) or a temp file |
| Conditionals | Address patterns only | Full if/else, loops, functions |
| Learning curve | Gentle for substitution | Steeper, but it is a real language |
| Typical one-liner | sed -i 's/http/https/g' f | awk '{s+=$3} END {print s}' f |
Which one, when
Changing a setting in a config file
Use sed
Anchored substitution in place, with a backup. This is the bread and butter of scripted server administration.
$ sed -i.bak "s/^PORT=.*/PORT=8080/" .env Summing a column of numbers
Use awk
sed cannot do arithmetic at all. awk keeps a running total and prints it at the end — four characters of real programming.
$ awk '{sum += $4} END {print sum}' sales.txt Extracting a column from command output
Use awk
awk collapses runs of whitespace automatically, which is exactly what aligned command output needs and what cut cannot handle.
$ ps aux | awk '{print $2, $11}' Deleting comment and blank lines
Use sed
Address patterns make this a one-liner: match and delete. Perfect for reading the effective content of a config file.
$ sed '/^#/d; /^$/d' nginx.conf Counting occurrences and ranking them
Use awk
Associative arrays build a frequency table in one expression — the kind of thing that would otherwise need a script or a spreadsheet.
$ awk '{count[$1]++} END {for (ip in count) print count[ip], ip}' access.log | sort -rn | head Gotchas worth knowing
- sed -i behaves differently on macOS: BSD sed requires an argument, even empty (sed -i '' …). Use -i.bak for scripts that must run on both.
- Always preview a sed substitution without -i first, or keep a backup. It is fast enough to ruin a file before you finish reading the command.
- In awk, wrap the program in single quotes so the shell leaves $1 alone — with double quotes the shell eats the dollar signs.
- sed s/…/ replaces only the first match per line unless you add the g flag. Forgetting it produces half-finished edits that look correct at a glance.
- Neither handles quoted CSV where a comma can appear inside a field. That needs a real parser.
Frequently asked questions
Can awk do everything sed does?
Broadly yes — awk has sub() and gsub() — but in-place editing is awkward and simple substitutions read worse. Using the right tool keeps the command readable.
Which is faster?
For simple substitution, sed. For column work, awk wins by not needing several piped stages. In practice both process hundreds of MB per second and the difference rarely matters.
Should I learn one or both?
Learn sed s/// and awk '{print $N}' first — those two forms cover most daily use. Go deeper only when a real problem asks for it.
What about perl or python for this?
They are more capable and appropriate for complex transformations. sed and awk win on being installed everywhere and being far shorter for the common cases.
Full guides for both
Stream-edit text: substitute, delete lines, and edit files in place with -i.
awkPull columns out of any output, filter rows, and compute sums — the shell's spreadsheet.
cutSlice fields or character ranges out of each line — quick column extraction for delimited data.
grepFind lines matching a pattern in files or piped input — the workhorse of text search.
Put it into practice
Other comparisons
Both copy files over SSH. rsync sends only what changed; scp sends everything, every time.
curl vs wgetcurl is an HTTP client for talking to services; wget is a downloader for retrieving files.
symbolic link vs hard linkA symlink stores a path and can break; a hard link is a second real name for the same file.
grep vs ripgrep (rg)grep is everywhere; ripgrep is dramatically faster on code and respects .gitignore by default.