Cheat Sheet

sed Examples

sed edits text as it streams through a pipe or over a file: replace, delete, insert, print. Every example here is paste-ready, and the macOS differences that break sed -i for Mac users get their own section.

Last updated September 11, 2026

Replace Text

The substitute command is most of what sed gets used for. replaces the first occurrence on each line; makes it every occurrence.

CommandWhat it does
Replace the first match on each line
Replace every match ( = global)
Replace only the 2nd match on each line
Case-insensitive match (GNU sed; BSD lacks )
Any delimiter works; use or when the text has slashes
is the whole match: error becomes [error]
Substitute only on lines matching a pattern
Substitute only on line 3
Strip trailing whitespace
Works on piped input too (GNU sed prints as newline)

Edit Files In Place

Without , sed prints the result and leaves the file alone. That is the safe way to test an expression first.

is the one flag that is not portable, and it is the single most common reason a sed command fails. GNU sed on Linux takes . BSD sed on macOS reads that as a backup filename extension and stops with or ; it needs an empty argument, . Only runs unchanged on both.

CommandWhat it does
Dry run: prints the result, file untouched
Edit the file in place (GNU sed / Linux only)
The same edit on macOS (BSD sed)
In place, keeping the original as file.bak (works everywhere)
The portable long way, no at all

sed on macOS

macOS ships BSD sed, and the biggest difference is : BSD requires a backup extension argument, GNU does not. on a Mac fails with "invalid command code" or "undefined label" because gets read as the backup extension.

CommandWhat it does
In-place edit on macOS (empty string = no backup)
Portable form: same command on macOS and Linux
Portable, without keeping the backup
Installs GNU sed as , which takes Linux syntax

Other BSD gaps to know: no case-insensitive flag, and / insert text needs a real newline after the backslash. for extended regex works on both.

Multiple Files

sed takes as many files as you give it, but rewrites every one of them. Run the command without on a single file first.

CommandWhat it does
Edit every .conf in the directory
Edit every matching file in a tree (see the grep cheat sheet)
Same, safe with spaces in filenames
The find equivalent
The macOS spelling of that command
Read many files without changing any of them
With , is each file's last line, not the last file's

Recursion is the caller's job: sed itself has no recursive flag ( means extended regex). Filtering with first also keeps the mtime of files that did not match.

Delete Lines

CommandWhat it does
Delete lines matching a pattern
Delete empty lines
Delete comments and empty lines
Delete the first line (drop a header)
Delete the last line
Delete lines 2 through 5
Delete from line 10 to the end
Delete from one pattern to another, inclusive
Delete everything except matching lines (same as )

turns off the default print-every-line behaviour, so prints only what you select.

CommandWhat it does
Print line 5 only
Print lines 2 through 4
Print the last line
Print matching lines (grep in sed clothing)
Print from one pattern to another
Print the first 10 lines, then quit (fast on huge files)
Every 3rd line starting at 1 (GNU only)
Print only the rewritten lines: extract a value
Write matching lines to another file ()
Print the line numbers of matches, not the lines

Insert and Append

inserts before a line, appends after it, replaces it entirely.

CommandWhat it does
Insert a line at the top (GNU syntax)
Append a line at the end
Add a line after each match
Add a line before each match
Replace the whole matching line
Append after a specific line number

BSD/macOS sed wants a backslash and a literal newline after , , and ; the one-line GNU forms above fail there. Use , or:

sed -i '' '1i\
header line
' file

Regex and Capture Groups

sed's default dialect is basic regex (BRE): groups and / need backslashes. switches to extended regex and works on both GNU and BSD sed ( is the older GNU spelling).

CommandWhat it does
BRE capture groups: "Doe, Jane" becomes "Jane Doe"
Same with -E: no backslashes on the parens
(one or more) needs -E
(optional) needs -E
Alternation needs -E
The BRE spelling of
First field of a colon-separated file
Collapse runs of whitespace

sed has no or in any dialect: use and . is greedy and there are no lazy quantifiers, so match "up to the next X" with .

Multiple Commands

CommandWhat it does
Run several expressions in order
Same, separated by semicolons
Group commands to run on matching lines ( steps to the next line)
Read commands from a script file, one per line
Join lines in pairs: pulls in the next line, then replace the newline

sed works line by line, so a plain never matches. The classic join-all-lines one-liner pulls the file into the buffer first (GNU sed):

sed ':a;N;$!ba;s/\n/ /g' file

For simple newline jobs, or is easier to read.

Variables and Special Characters

CommandWhat it does
Double quotes let the shell expand
Another delimiter when the variable holds slashes
Command substitution works too
A literal in the replacement must be escaped
A literal backslash is (doubled again by shell quoting)
To match a literal , escape it in the pattern
Escape to match them literally
Remove every double quote from the text
Remove every single quote (swap the outer quotes round)
A literal inside a single-quoted expression: close, escape, reopen

Options

The shape is . Everything else is a command letter inside the script.

OptionWhat it does
Suppress the automatic print, so only outputs
Add an expression; repeat it for several
Read the commands from a file
Edit in place (GNU); on macOS it must be
Edit in place and keep a backup, the portable spelling
Extended regex: , , and need no backslash
GNU-only spelling of ; prefer
Treat each input file separately, so is its own last line
Split input on NUL, for pairing with (GNU)
Show how GNU sed parses and runs the script
Tells you whether you have GNU sed or BSD sed

Command Letters

LetterWhat it does
Substitute, the command nearly every script uses
Transliterate character by character, like
Delete the line
Print the line, normally with
Append a line after this one
Insert a line before this one
Replace the whole line
Quit without reading the rest of the input
Print the line number
Write the line to a file
Read a file in after the line
Print the current line and load the next
Add the next line to the buffer, keeping both
Copy, append and swap with the hold space
Branch and loop, what is built from
Show invisible characters, with marking the line end

is the quickest way to see a stray carriage return or a tab that a pattern keeps missing.

sed on Windows

Windows has no built-in sed. Git Bash and WSL both ship GNU sed, so Linux syntax works as written; means the shell is cmd or PowerShell rather than one of those.

CommandWhat it does
Works unchanged in Git Bash and WSL (GNU sed)
Call Linux sed from PowerShell or cmd
The PowerShell equivalent, no sed needed
Strip the carriage returns a Windows editor leaves behind
Fixes on a script edited in Windows

Carriage returns are the usual reason a pattern anchored with matches nothing on a file that came from Windows.

Gotchas

  • needs on macOS and plain on Linux. is the only spelling that works on both unchanged. and on a Mac are almost always this.
  • is BSD sed refusing the one-line GNU , and forms. Add the backslash and a real newline, or use .
  • usually means the delimiter also appears inside your pattern or replacement, or the expression reached sed unquoted.
  • No , no , no lazy in sed regex, in any version. Use , , and .
  • An unescaped in the replacement inserts the whole match. This bites when the replacement is a shell variable containing .
  • Prefer over for extended regex: GNU sed takes both, BSD sed only .
  • Single-quote sed expressions unless you need a variable expanded. Inside double quotes the shell eats backslashes and before sed sees them.
  • grep answers "which lines", sed rewrites them, awk works per column. See the grep cheat sheet and awk cheat sheet.

sed FAQ

Why does sed -i not work on macOS?

macOS ships BSD sed, where -i requires a backup extension as an argument. GNU sed accepts sed -i 's/a/b/' file, but on a Mac that reads s/a/b/ as the backup extension and fails with an 'undefined label' or 'invalid command code' error. Write sed -i '' 's/a/b/' file on macOS (empty string means no backup). The form that works on both is sed -i.bak 's/a/b/' file, deleting the .bak after. Or brew install gnu-sed and use gsed with the Linux syntax.

Why is my sed command not replacing text in the file?

Usually the file was never written. Without -i, sed prints the result to the terminal and leaves the file alone, so check that flag first; on macOS it has to be -i '' or the expression is eaten as a backup extension. If the command runs clean but matches nothing, the pattern is the problem: . * [ ] and the delimiter itself are regex, so a literal dot or slash needs escaping. A file saved on Windows ends every line with a carriage return, which is why patterns anchored with $ silently fail; run sed -i 's/\r$//' file first. One more: sed -i writes a temp file and renames it over the original, so an editor that still has the old version open can save it straight back over your change.

How do I use a variable in a sed command?

Switch to double quotes so the shell expands it: sed "s/localhost/$HOST/g" config. Two things break this: a slash inside the variable ends the pattern early, so use another delimiter (sed "s|/var/www|$DOCROOT|g"), and an & or \ in the variable is interpreted by sed itself. For variables you control, that is fine; for arbitrary input, escape it first or reach for awk -v, which passes variables without re-parsing them.

How do I replace a string that contains slashes?

Use a different delimiter; sed accepts almost any character after the s. sed 's|/var/www|/srv/http|g' and sed 's#http://#https://#g' both work with no escaping. The alternative is escaping every slash (s//var/www/... ), which is unreadable. Regex specials like . * [ ] still need a backslash regardless of delimiter, since only the delimiter changes.

How do I replace a string in multiple files at once?

Glob when the files are in one directory: sed -i 's/old/new/g' *.conf. Across a tree, let grep find the files and xargs feed them to sed: grep -rl 'old' src/ | xargs sed -i 's/old/new/g'. This touches only files that actually match, which keeps timestamps honest. On macOS add the empty backup argument: xargs sed -i '' 's/old/new/g'. Test the expression on one file before running it over hundreds.

Related cheat sheets