Imagine needing to change a specific configuration setting across dozens of files, or update a repeated piece of text throughout a large log file. Manually editing each instance would take forever. This is precisely where the powerful Linux sed command (Stream EDitor) excels. The sed command specializes in finding and replacing strings in files, automating text transformations that would otherwise consume hours of manual editing with simple, precise commands.
For example, a single sed command can update IP addresses across dozens of configuration files after a network migration, standardize date formats in thousands of log entries, or sanitize sensitive data before sharing files. Whether you’re replacing a single word in one file or transforming text patterns across entire directory trees, sed handles find-and-replace operations with speed and reliability.
This guide covers everything from basic string replacement to advanced pattern matching and multi-file editing. By the end, you’ll know how to find and replace text effectively in any scenario and avoid the common pitfalls that trip up both newcomers and experienced users.
What You’ll Learn
In this guide, you’ll learn how to:
- Perform basic and global text replacements with precision
- Use regular expressions for advanced pattern matching
- Handle special characters and choose the right delimiters
- Apply line-specific transformations and targeted edits
- Combine
sedwith other commands for complex workflows - Troubleshoot common issues and cross-platform differences
Understanding the sed Command
If you’re new to sed, think of it as a streaming text editor that reads input line by line, applies the instructions you provide, and writes the result without launching a full-screen editor. GNU sed is included with almost every Linux distribution, and the official GNU sed manual is a great deep-dive when you need to explore edge cases.
At its simplest, you can replace one word with another and print the result without touching the original file:
sed 's/Linux/GNU\/Linux/' release-notes.txt
Adding -i turns that same command into an in-place edit. Test without -i first so you can confirm the output before writing to disk.
Here’s the general syntax for finding and replacing text:
sed [-i[SUFFIX]] 's/SEARCH_REGEX/REPLACEMENT/FLAGS' INPUTFILE
Let’s break it down step by step:
-i: This tellssedto edit the file in place. If you want to keep a backup of the original file, you can add an extension like.bak(e.g.,-i.bak). On macOS (BSD sed), if you don’t want a backup, you must provide an empty string as an argument to-i, for example,-i ''. GNU sed allows-iwithout an extension if no backup is desired.s: The substitute command, used for search-and-replace operations.- Delimiters (
/): While/is the default delimiter, you can use others like|or:if it makes your command easier to read. SEARCH_REGEX: The string or regular expression pattern you’re looking for.REPLACEMENT: The text you want to replace it with.g: The global flag. Without it, only the first match on each line is replaced. Add this to replace all matches.
With this foundation, you’re ready to start using sed to tackle text editing tasks of all sizes.
Quick Reference: Common sed Flags
Before diving into examples, here’s a quick reference table of the most frequently used sed flags:
| Task | Options | What They Do |
|---|---|---|
| Edit files in place safely | -i, -i.bak | Apply changes directly to the file, optionally keeping a backup with a suffix such as .bak. |
| Preview matches before writing | -n '/pattern/p' | Suppress automatic printing so only lines matching the pattern are shown. |
| Run multiple edits at once | -e 's/a/b/' -e 's/c/d/' | Chain several substitutions in a single command. |
| Use extended regular expressions | -E | Enable features like grouping without extra escaping for parentheses and braces. |
| Stream output immediately | -u | Turn on unbuffered output to reduce latency in pipelines and log monitoring. |
| Replace every match on a line | s/old/new/g | Add the global flag so every occurrence is replaced, not just the first match per line. |
| Match text without case sensitivity | s/text/replacement/gI | Include the I flag so GNU sed treats uppercase and lowercase letters the same. |
Check and Install sed
Most Linux installations include sed by default, but stripped-down containers and rescue images sometimes leave it out. Verify that it’s available before you start scripting:
command -v sed
If the command returns a path, you’re set. Otherwise install sed with your distribution’s package manager.
Ubuntu and Debian-based distributions:
sudo apt update
sudo apt install sed
Fedora, RHEL, Rocky Linux, and AlmaLinux:
sudo dnf install sed
Arch Linux and Manjaro:
sudo pacman -S sed
openSUSE:
sudo zypper install sed
Alpine Linux:
sudo apk add sed
macOS (Homebrew):
brew install gnu-sed
Homebrew installs GNU sed as gsed so you can opt into GNU-only features like the I flag while keeping the system’s BSD sed untouched. For other platforms, building from source is rarely necessary unless you’re targeting a specific sed version.
Basic sed Command Usage for String Replacement
Let’s start with the basics by looking at how to find and replace text in a file. Here’s an example using a file called file.txt with the following content:
123 Foo foo foo
foo /bin/bash Ubuntu foobar 456
Example 1: Replace the First Instance of a String
To replace only the first occurrence of a string on each line, you can use the following command:
sed 's/foo/linux/' file.txt
Output:
123 Foo linux foo linux /bin/bash Ubuntu foobar 456
Notice that only the first foo on each line was replaced, while other instances remain unchanged. This prints the modified text to your terminal; add -i (or -i.bak) when you’re ready to write the change back to disk.
Example 2: Replace All Occurrences of a String
To replace every occurrence of a string on each line, add the g flag for “global”:
sed 's/foo/linux/g' file.txt
Output:
123 Foo linux linux linux /bin/bash Ubuntu linuxbar 456
This replaces every instance of foo, including when it appears as part of another word, such as foobar. The original file remains untouched until you repeat the command with -i.
Example 3: Avoid Matching Substrings
If you don’t want sed to replace partial matches (like foo inside foobar), you can use word boundaries. In GNU sed, you can use \b as follows:
sed 's/\bfoo\b/linux/g' file.txt
The
\bword boundary is supported in GNU sed. On macOS (BSD sed), use[[:<:]]foo[[:>:]]instead:sed -E 's/[[:<:]]foo[[:>:]]/linux/g' file.txt
Output:
123 Foo linux linux linux /bin/bash Ubuntu foobar 456
Notice that capital Foo remains unchanged because word boundaries are case-sensitive. The pattern \bfoo\b only matches lowercase “foo” as a complete word, leaving foobar (partial match) and Foo (different case) untouched.
Example 4: Perform Case-Insensitive Replacement
To make the replacement case-insensitive, include the I flag (GNU sed only):
sed 's/foo/linux/gI' file.txt
The
Iflag is available in GNU sed. On macOS (BSD sed), preview the change with a character class for case-insensitivity, such as[Ff]oo:sed 's/[Ff]oo/linux/g' file.txt
If you do want to edit in place on macOS, provide an empty string to -i so BSD sed skips creating a backup file:
sed -i '' 's/[Ff]oo/linux/g' file.txt
Output:
123 linux linux linux linux /bin/bash Ubuntu linuxbar 456
Example 5: Replace Strings Containing Special Characters
If the string you’re replacing includes special characters like /, you’ll need to escape them with a backslash (\). For example, to replace /bin/bash with /usr/bin/zsh:
sed 's/\/bin\/bash/\/usr\/bin\/zsh/g' file.txt
Or, use a different delimiter (like |) to make the command more readable. In fact, you can use almost any character as a delimiter, such as #, :, or _, as long as it does not appear in your search pattern or replacement string:
sed 's|/bin/bash|/usr/bin/zsh|g' file.txt
Output:
123 Foo foo foo foo /usr/bin/zsh Ubuntu foobar 456
Example 6: Preview and Back Up Edits
- Test Before Committing Changes: Run your
sedcommands without the-ioption to preview the changes before modifying the file. - Always Create Backups: Use
-i.bakto save a backup of the original file, just in case. For example:
sed -i.bak 's/foo/linux/g' file.txt
Ready to try more advanced techniques? The next examples introduce regular expressions, line targeting, and multi-file workflows so you can adapt sed to complex real-world edits.
Advanced sed Operations
Once you’ve mastered the basics, you can move on to sed‘s more advanced capabilities. Regular expressions let you match flexible patterns instead of literal strings, opening up possibilities like finding all IP addresses, standardizing date formats, or extracting specific data structures. Combined with line-specific operations and multi-file workflows, sed becomes an even more powerful tool for handling intricate text manipulation tasks.
Example 7: Replace Patterns with Regular Expressions
Regular expressions allow you to match patterns, not just literal strings. For instance, to replace all 3-digit numbers with the word number:
sed 's/\b[0-9]\{3\}\b/number/g' file.txt
Output:
number Foo foo foo foo /bin/bash Ubuntu foobar number
This matches only 3-digit numbers (e.g., 123 or 456) and replaces them, leaving other numbers unaffected.
Example 8: Reuse Matched Text with &
The & character corresponds to the matched pattern and can be used in the replacement string. For example, if you want to surround every 3-digit number with curly braces:
sed 's/\b[0-9]\{3\}\b/{&}/g' file.txt
Output:
{123} Foo foo foo
foo /bin/bash Ubuntu foobar {456}
Here, {&} inserts the matched number between the curly braces.
Example 9: Target Specific Lines for Substitutions
You can target specific lines or ranges of lines for replacement:
- Replace text on a specific line (e.g., line 2):
sed '2s/foo/linux/' file.txt
- Replace text in a range of lines (e.g., lines 2 to 4):
sed '2,4s/foo/linux/' file.txt
The sed command gives you fine-grained control over where replacements occur, avoiding unintended changes.
Example 10: Edit Many Files with find and sed
When working with large files or directories, combining sed with other tools like the find command or the grep command becomes incredibly useful. However, recursive operations require careful attention to avoid corrupting binary files or making unintended changes.
The following command modifies every file in the directory tree, including binaries, images, databases, and executables. Running it without proper filtering can corrupt system files or application data, so always test first and restrict the scope to specific file types.
- Recursive Search and Replace (USE WITH EXTREME CAUTION):
find . -type f -exec sed -i 's/foo/bar/g' {} +
Safe approach: Before running any recursive sed operation, perform a dry run to see which files would be affected:
# Preview files that would be modified
find . -type f -print
# Or test the sed command without making changes
find . -type f -exec sed -n 's/foo/bar/gp' {} + | less
- Target Specific File Types (RECOMMENDED): Replace
foowithbaronly in.txtfiles:
find . -type f \( -name "*.txt" -o -name "*.conf" -o -name "*.cfg" \) -exec sed -i.bak 's/foo/bar/g' {} +
This safer approach limits changes to text files and creates backups automatically. Group the filename tests inside escaped parentheses so -type f applies to every branch.
Using grep to Target Only Matching Files: Search for files containing foo and replace it with bar, while creating backups:
grep -IlZ 'foo' . | xargs -0 sed -i.bak 's/foo/bar/g'
This approach only modifies files that actually contain the search pattern, reducing the risk of unnecessary changes. The -Z and -0 flags handle filenames with spaces correctly. For more details on the grep command and its advanced search capabilities, check out our comprehensive grep command guide.
Example 11: Stream Output with Unbuffered Mode
When you need sed to flush its output promptly, such as in streaming pipelines or when feeding logs into another process, enable unbuffered mode with the -u option:
sed -u 's/foo/bar/g' logfile.txt
Unbuffered mode prevents output from being held in sed’s buffers, which reduces latency but can slightly slow down throughput on very large files. GNU sed supports
-u. BSD sed (macOS) lacks this flag and returns anillegal optionerror, so install GNU sed (for example,brew install gnu-sedand rungsed -u ...) or pair sed with a line-buffering tool such asstdbuf -o0from coreutils (installable viabrew install coreutils) to approximate the same behavior. This trade-off makes-uideal for real-time log monitoring or interactive pipelines where immediate output matters more than raw processing speed.
Troubleshooting Common sed Issues
While sed is powerful, you might encounter a few common issues. Here’s how to troubleshoot them:
1. Changes Not Happening or Incorrect Replacements
- Forgetting Global Replacement (
g): If only the first match on each line is replaced, ensure you’ve added thegflag to your substitute command (e.g.,s/old/new/g) to replace all occurrences. - Regex Errors: Special characters in your search pattern (like
.,*,[,\) need to be escaped with a backslash (\). For example, to match a literal dot, use\.. Alternatively, for paths with slashes, use a different delimiter:sed 's|/path/to/old|/path/to/new|g'. - Word Boundaries: If
sedreplaces parts of words you didn’t intend (e.g., “man” in “manual”), use word boundaries. For GNU sed, use\b(e.g.,s/\bman\b/person/g). For BSD sed (macOS), use[[:<:]]and[[:>:]](e.g.,s/[[:<:]]man[[:>:]]/person/g). - Case Sensitivity: By default,
sedis case-sensitive. For case-insensitive search in GNU sed, use theIflag (e.g.,s/text/replacement/gI). For BSD sed, you might need to use character classes like[Tt][Ee][Xx][Tt].
2. Differences Between GNU sed (Linux) and BSD sed (macOS)
Syntax and feature differences between GNU sed (common on Linux) and BSD sed (used on macOS) are a frequent source of confusion:
- In-place Editing (
-i):- GNU sed:
-iedits in place without a backup.-i.bakcreates a backup. Note that GNUsedcreates the backup file specified with-i.SUFFIXeven if no actual changes are made to the file content. - BSD sed:
-irequires an extension for backup (e.g.,-i '.bak'). For no backup, provide an empty string:-i ''.
- GNU sed:
- Extended Regular Expressions:
- GNU sed: Supports both
-rand-E. The POSIX standard is-E, which is recommended for better portability. - BSD sed: Uses
-E.
- GNU sed: Supports both
Always check your system’s
man sedpage for specifics.
3. “sed: -i may not be used with stdin” Error
The -i option (for in-place editing) modifies files directly and cannot be used when sed receives input from a pipe (stdin). If you’re piping output from another command to sed and want to save the changes, redirect the output to a new file:
some_command | sed 's/old/new/g' > output_file.txt
If you need to modify the original file in such a scenario, use a temporary file or more advanced shell constructs.
4. Avoiding Accidental File Modification
Before using -i to modify a file directly, it’s crucial to:
- Test without
-i: Run yoursedcommand without-ifirst. This prints the modified output to the terminal, allowing you to verify the changes are correct before applying them to the file. - Create Backups: Use
-i.bak(GNU sed) or-i '.bak'(BSD sed) to create a backup of the original file. If something goes wrong, you can easily restore it.
5. Using sed on Binary Files
sed is designed for text files. Using it on binary files (like images or executables) can corrupt them. For binary file manipulation, tools like xxd or hexedit are more appropriate.
Related Linux Commands for Text Processing
While sed is powerful for stream editing and text transformations, combining it with other Linux text-processing commands becomes even more useful. Here are complementary tools with practical examples:
- grep – Search for patterns in files and filter text before or after
sedprocessing. Example:grep -IlZ "ERROR" -- *.log | xargs -0 sed -i.bak 's/ERROR/WARN/g'finds only the log files that contain the string (skipping binaries) and updates them safely. - awk – Extract and manipulate columnar data alongside pattern-based transformations. Example:
awk '{print $3}' access.log | sed 's|/old/path|/new/path|g'extracts the third field from log files then transforms paths in the output. - tr – Translate or delete characters for simple character-level transformations. Example:
cat config.ini | tr -d '\r' | sed 's/^#//g'removes Windows line endings then strips comment markers. - cut – Extract sections from lines of text based on delimiters or character positions. Example:
cut -d':' -f1,7 /etc/passwd | sed 's|/bin/bash|/bin/zsh|g'extracts username and shell fields then updates default shells. - sort – Sort lines of text before processing with
sed. Example:sort access.log | sed -n '/ERROR/p'sorts log entries then extracts only error lines for analysis. - uniq – Remove or identify duplicate lines in processed output. Example:
sed 's/^[[:space:]]*//' file.txt | sort | uniq -cstrips leading whitespace, sorts lines, and counts duplicates. - tail – Monitor and process the end of files in real-time. Example:
tail -f /var/log/syslog | sed -u 's/ERROR/[ERROR]/g'highlights errors in live logs.
Mastering these commands together creates a powerful text-processing toolkit for any Linux administrator or developer.
Conclusion
The sed command delivers powerful find-and-replace capabilities that turn hours of manual text editing into seconds of automated work. Whether you’re replacing a simple string in a single file or transforming complex patterns across thousands of configuration files, sed handles it with precision and speed. By mastering the substitution syntax, regular expressions for pattern matching, and safe multi-file workflows with tools like find and grep, you gain complete control over text replacement in any Linux environment. For advanced pattern matching and edge cases, consult the official GNU sed manual to unlock even more find-and-replace techniques.