sed
| Since: | All Linux | |
|---|---|---|
| macOS(2001 Cheetah) | ||
| Bash 1.0(1989) |
sed (Stream EDitor) is a command that processes text line by line. It performs editing operations such as substitution, deletion, insertion, and extraction without opening a file. It is commonly used in scripts and automated workflows.
Syntax
sed [options] 'command' [file...]
sed [options] -e 'command1' -e 'command2' [file...]
Commands and Options
| Command / Option | Description |
|---|---|
| s/before/after/ | Replaces the first match on each line. |
| s/before/after/g | Replaces all matches on each line (global). |
| s/before/after/i | Replaces matches case-insensitively. |
| -i file | Edits the file in place (directly). |
| -i.bak file | Saves a backup to .bak before editing in place. |
| -n | Suppresses default output (used together with the p command). |
| /pattern/d | Deletes lines matching the pattern. |
| /pattern/p | Prints lines matching the pattern (used together with -n). |
| Nd | Deletes line N. |
| N,Md | Deletes lines N through M. |
| /pattern/a text | Appends text after each matching line. |
| /pattern/i text | Inserts text before each matching line. |
Sample Code
The following files are used as examples.
data.txt
Hello World foo foo This is a foo test Another line here
config.txt
# Database settings host=localhost # Port number port=3306
s/before/after/ replaces the first match on each line. Adding g replaces all matches.
sed 's/foo/bar/' data.txt Hello World bar foo This is a bar test Another line here
The following example demonstrates this:
sed 's/foo/bar/g' data.txt Hello World bar bar This is a bar test Another line here
/pattern/d deletes lines matching the pattern. The example below removes comment lines (lines starting with #).
sed '/^#/d' config.txt host=localhost port=3306
/^$/d removes blank lines.
printf "line1\n\nline2\n\nline3\n" | sed '/^$/d' line1 line2 line3
Combining -n and the p command extracts only specific lines.
sed -n '2,4p' config.txt host=localhost # Port number port=3306
-e runs multiple substitutions at once.
sed -e 's/foo/bar/g' -e 's/World/Earth/' data.txt Hello Earth bar bar This is a bar test Another line here
-i edits the file directly (in-place substitution). -i.bak creates a backup before editing.
sed -i 's/old/new/g' file.txt
The following example demonstrates this:
sed -i.bak 's/old/new/g' file.txt
Removes leading and trailing whitespace (trim).
echo " hello world " | sed 's/^[[:space:]]*//; s/[[:space:]]*$//' hello world
Deletes the first line (useful for skipping CSV headers, for example).
echo -e "name,age\nKiryu Kazuma,37\nMajima Goro,39" | sed '1d' Kiryu Kazuma,37 Majima Goro,39
Using Regular Expressions
sed supports POSIX extended regular expressions. With GNU sed, use the -E option to enable ERE syntax without escape characters.
Deletes lines consisting only of digits (BRE).
printf "abc\n123\nfoo456\n789\n" | sed '/^[0-9]*$/d' abc foo456
Use -E for extended regular expressions (ERE). No backslash needed for + and ?.
printf "color\ncolour\n" | sed -E 's/colou?r/hue/g' hue hue
Use capture groups (\1) to preserve part of the match. Converts "YYYY-MM-DD" to "DD/MM/YYYY".
echo "2025-03-28" | sed -E 's/([0-9]{4})-([0-9]{2})-([0-9]{2})/\3\/\2\/\1/'
28/03/2025
BSD sed (macOS) vs GNU sed (Linux)
macOS ships with BSD sed, while Linux ships with GNU sed. They differ in option syntax and regex handling, so a script that works on one platform may fail on the other. This is especially important when your local machine runs macOS but your CI/CD or servers run Linux.
| Feature | GNU sed (Linux) | BSD sed (macOS) |
|---|---|---|
| In-place edit (no backup) | sed -i 's/a/b/g' file | sed -i '' 's/a/b/g' file (empty string required) |
| In-place edit with backup | sed -i.bak 's/a/b/g' file | sed -i.bak 's/a/b/g' file (same) |
| Extended regex flag | -r or -E | -E only (-r is not supported) |
| Insert newline with \n | sed 's/a/b\n/g' (works directly) | Requires a literal newline ($'\n', etc.) |
| Insert tab with \t | sed 's/a/\t/g' (works directly) | Requires a literal tab ($'\t', etc.) |
| Case-insensitive substitution | sed 's/foo/bar/Ig' (I flag) | Not supported |
The backup-extension form works on both platforms.
sed -i.bak 's/localhost/127.0.0.1/g' config.txt
config.txt is rewritten; the original is saved as config.txt.bak.
For extended regex, use -E — it is supported by both GNU sed and BSD sed (GNU sed also accepts -r, but BSD sed does not).
sed -E 's/colou?r/hue/g' data.txt hue hue
Newline and tab insertion differs between the two, so using printf or $'\n' is the most portable approach.
sed "s/:/$(printf '\n')/g" data.txt
To use GNU sed on macOS, install it via Homebrew. After installation, use the gsed command.
brew install gnu-sed gsed -i 's/old/new/g' file.txt
You can also detect the environment in a script and switch automatically.
if sed --version > /dev/null 2>&1; then
SED="sed"
else
SED="gsed"
fi
$SED -i 's/old/new/g' file.txt
GNU sed supports --version but BSD sed does not, which makes this a reliable way to detect the environment.
Common Mistakes
Common mistake 1: slash as delimiter
Using / as the delimiter makes path substitution awkward and can cause syntax errors. You can use any character as the delimiter — |, @, #, etc. — so choose a different one when the substitution involves slashes.
sed 's|/var/log|/var/www|g' file.txt
Common mistake 2: using p without -n
Using p without -n causes each line to be printed twice — once by the normal output and once by p. To extract specific lines only, always pair -n with p.
sed 'p' data.txt Hello World foo foo Hello World foo foo This is a foo test This is a foo test Another line here Another line here
The following example demonstrates this:
sed -n 'p' data.txt Hello World foo foo This is a foo test Another line here
The following example demonstrates this:
sed -n '2,4p' data.txt This is a foo test Another line here
Notes
When using sed -i for in-place editing, creating a backup first or working within a git-managed repository helps protect your files. On macOS, BSD sed is used instead of GNU sed, so some option syntax differs (for example, macOS requires an empty string: sed -i "").
For more complex text processing, use awk. For simple searches, see also grep.
If you find any errors or copyright issues, please contact us.