sed Command in Linux: Find and Replace Strings in Files

Learn how to use the sed command in Linux for text editing with practical examples, tips, and advanced techniques.

Last updatedAuthorJoshua JamesRead time10 minGuide typeLinux Commands

The Linux sed command handles repetitive text edits that are too small for a full script and too risky to do by hand. A single substitution can find and replace text in one file, preview the result, or apply the same change across a guarded set of configuration and log files.

Most Linux systems use GNU sed, while BSD sed and Homebrew’s gsed notes call out the places syntax changes. Dry-run checks and -i.bak backups appear before recursive replacement because find-and-replace commands can touch many files quickly.

Understand the sed Command

The name means stream editor: sed reads input line by line, applies the instructions you provide, and writes the result without launching a full-screen editor. GNU sed ships with almost every Linux distribution, while Homebrew installs the same GNU tool as gsed so it does not replace macOS’s system BSD sed. The official GNU sed manual covers additional edge cases.

In practice, a single command can update IP addresses across dozens of configuration files after a network migration, standardize date formats in thousands of log entries, or strip sensitive fields before sharing data. At its simplest, you 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.

Use this general shape for substitution commands:

sed [OPTIONS] 's/SEARCH_REGEX/REPLACEMENT/FLAGS' INPUTFILE

The most important parts are:

  • -i: Edit the file in place. Add a suffix such as -i.bak to keep a backup copy. On macOS (BSD sed), no-backup editing requires an empty argument, -i '', while GNU sed accepts -i by itself.
  • s: The substitute command, used for search-and-replace operations.
  • Delimiters (/): / is the default delimiter, but |, :, or another character can make path replacements easier to read.
  • SEARCH_REGEX: The literal string or regular expression pattern to match.
  • REPLACEMENT: The text that replaces each match.
  • g: The global flag. Without it, only the first match on each line is replaced. Add this to replace all matches.

That syntax is enough for most file edits. The rest of the examples add safety checks, broader match patterns, and multi-file workflows.

Quick Reference: Common sed Flags

Keep these common sed flags in mind as the examples build from simple substitutions to safer multi-file edits:

TaskOptionsWhat They Do
Edit files in place safely-i, -i.bakApply 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-EEnable grouping without extra escaping for parentheses and braces.
Stream output immediately-uTurn on unbuffered output to reduce latency in pipelines and log monitoring.
Replace every match on a lines/old/new/gAdd the global flag so every occurrence changes, not just the first match per line.
Match text without case sensitivitys/text/replacement/gIUse the GNU sed I flag so uppercase and lowercase letters match the same pattern.

Verify sed Is Available

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
/usr/bin/sed

On GNU sed, confirm the installed version with:

sed --version | head -1
sed (GNU sed) 4.9

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

apk add sed

macOS (Homebrew)

brew install gnu-sed

Homebrew installs GNU sed as gsed, so Linux-oriented commands that rely on GNU-only features can run on macOS without replacing the system BSD sed. For other platforms, building from source is rarely necessary unless a script depends on a specific sed release.

Alpine Linux ships BusyBox sed by default, which lacks several GNU-specific features used here, including \b word boundaries, the I case-insensitive flag, and -u unbuffered mode. Running apk add sed installs the GNU sed package so the sed command resolves to the full GNU version.

Basic sed Command Usage for String Replacement

Start with a small file so the substitution behavior is easy to see. The examples in this section use file.txt with this 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, run:

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 replacement:

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 do not want sed to replace partial matches such as foo inside foobar, use word boundaries. GNU sed accepts \b for this pattern:

sed 's/\bfoo\b/linux/g' file.txt

The \b word 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 GNU sed I flag:

sed 's/foo/linux/gI' file.txt

The I flag is available in GNU sed. On macOS (BSD sed), preview a simple mixed-case pattern with a character class, such as [Ff]oo:

sed 's/[Ff]oo/linux/g' file.txt

For an in-place edit 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 contains /, escape each slash with a backslash. This command replaces /bin/bash with /usr/bin/zsh:

sed 's/\/bin\/bash/\/usr\/bin\/zsh/g' file.txt

A different delimiter, such as |, often reads better for paths. You can use almost any delimiter, including #, :, or _, as long as that character does not appear in the search pattern or replacement text:

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

A sed dry run is the same substitution without -i. It prints the proposed result to the terminal, which lets you inspect the change before writing anything to disk:

sed 's/foo/linux/g' file.txt
123 Foo linux linux
linux /bin/bash Ubuntu linuxbar 456

When the preview looks right, add -i.bak so sed writes the edit and keeps the original file as file.txt.bak:

sed -i.bak 's/foo/linux/g' file.txt

That preview-first pattern matters more as the match becomes broader. Regular expressions, line targeting, and recursive edits can save time, but they also need tighter scope and backups.

Use Advanced sed Operations

Regular expressions let sed match flexible patterns instead of literal strings. That opens up tasks such as standardizing numbers, wrapping matched text, targeting specific lines, and applying guarded replacements across a project tree.

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, such as 123 or 456, and replaces them while leaving other numbers unaffected.

Example 8: Reuse Matched Text with Ampersand

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:

To replace text on a specific line, such as line 2:

sed '2s/foo/linux/' file.txt

To replace text in a range of lines, such as lines 2 through 4:

sed '2,4s/foo/linux/' file.txt

If the range exceeds the file length, sed applies the edit through the end of the file.

The sed command gives you fine-grained control over where replacements occur, avoiding unintended changes.

Example 10: Edit Many Files with find and sed

Recursive replacements are where sed needs the most restraint. Combine it with the find command or the grep command so you can limit the files, preview the match set, and avoid binary files.

Before running any recursive sed operation, perform a dry run. The first command lists files that contain the search term, and the second previews changed lines without writing to disk:

# List files containing the search term
grep -rIl --exclude-dir=.git 'foo' ./project

# Preview substitutions in likely text configuration files
find ./project -path '*/.git' -prune -o -type f \( -name "*.txt" -o -name "*.conf" -o -name "*.cfg" \) -exec sed -n 's/foo/bar/gp' {} + | less

A broad recursive replacement can modify every regular file in the directory tree, including binaries, images, databases, and executables. Preview first, keep the target under a disposable or project-specific directory, and restrict the command to known text file types before adding -i.

  • Broad recursive replacement: Avoid this shape unless the tree is disposable or already filtered by another tool:
find ./project -path '*/.git' -prune -o -type f -exec sed -i.bak 's/foo/bar/g' {} +
  • Target specific file types: Replace foo with bar only in .txt, .conf, and .cfg files:
find ./project -path '*/.git' -prune -o -type f \( -name "*.txt" -o -name "*.conf" -o -name "*.cfg" \) -exec sed -i.bak 's/foo/bar/g' {} +

This safer approach limits the command to selected text-oriented extensions and creates backups automatically. Group the filename tests inside escaped parentheses so -type f applies to every branch.

To touch only files that actually contain the search pattern, pipe a null-delimited grep result into xargs and keep backups:

grep -rIlZ --exclude-dir=.git 'foo' ./project | xargs -0 -r sed -i.bak 's/foo/bar/g'

The -Z and -0 flags keep filenames with spaces, quotes, and newlines intact as they move through the pipeline. On GNU xargs, -r also prevents sed from running when grep finds no matches.

Example 11: Replace Newlines with sed

sed normally sees one line at a time, so a newline is not available to the search pattern unless you first pull more than one line into the pattern space. This GNU sed command joins a small file by replacing each newline with a space:

printf 'alpha\nbeta\ngamma\n' > lines.txt
sed ':a;N;$!ba;s/\n/ /g' lines.txt
alpha beta gamma

This pattern loads the whole file into memory, so use it for small lists or configuration fragments rather than huge logs. To go the other direction, GNU sed can place newline characters in the replacement side:

printf 'alpha beta gamma\n' | sed 's/ /\n/g'
alpha
beta
gamma

Example 12: 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 reduces latency but can slightly slow throughput on very large files. GNU sed supports -u. BSD sed (macOS) lacks this flag and returns an illegal option error, so install GNU sed and run gsed -u ... when a script needs unbuffered sed output. Use this mode for real-time log monitoring or interactive pipelines where immediate output matters more than raw processing speed.

Troubleshoot Common sed Issues

Even experienced users run into sed gotchas. The troubleshooting entries show the symptom, cause, and fix so you can resolve problems quickly.

1. Only the First Match on Each Line Is Replaced

Symptom: You expect every occurrence to change, but only the first match per line is affected:

echo "foo bar foo baz foo" | sed 's/foo/REPLACED/'
REPLACED bar foo baz foo

Cause: Without the g flag, sed replaces only the first match on each line.

Fix: Add the g (global) flag:

echo "foo bar foo baz foo" | sed 's/foo/REPLACED/g'
REPLACED bar REPLACED baz REPLACED

2. sed Replaces Partial Words Unexpectedly

Symptom: Replacing man also changes manual and command:

echo "man reads the manual command" | sed 's/man/person/g'
person reads the personual compersond

Cause: Without word boundaries, sed matches the pattern inside any word.

Fix: Use \b word boundaries (GNU sed) to match whole words only:

echo "man reads the manual command" | sed 's/\bman\b/person/g'
person reads the manual command

3. GNU sed vs BSD sed (macOS) Differences

Syntax differences between GNU sed (Linux) and BSD sed (macOS) are a frequent source of errors. The most common conflicts:

In-place editing (-i): Running a GNU-style sed -i on macOS produces an error because BSD sed requires an argument after -i:

# This works on GNU sed but fails on BSD sed (macOS)
sed -i 's/old/new/g' file.txt
sed: 1: "file.txt": invalid command code f

Fix: On macOS, provide an empty string for no backup or a suffix for a backup:

# BSD sed (macOS) - no backup
sed -i '' 's/old/new/g' file.txt

# BSD sed (macOS) - with backup
sed -i '.bak' 's/old/new/g' file.txt

Extended regex (-E vs -r): GNU sed supports both -r and -E for extended regex. BSD sed only supports -E. Use -E for cross-platform scripts.

Always check your system’s man sed page for specifics. When in doubt, use -E instead of -r for extended regex portability.

4. sed -i Fails on Piped Input

Symptom: Piping output to sed -i fails because in-place editing needs file paths:

cat file.txt | sed -i 's/old/new/g'
sed: no input files

Cause: The -i flag edits named files directly and cannot rewrite anonymous piped input.

Fix: Redirect the transformed stream to a new file instead:

printf 'old value\n' | sed 's/old/new/g' > output_file.txt

Verify: Confirm the output file contains the expected changes:

cat output_file.txt
new value

5. Avoid Accidental sed File Modification

Running sed -i with a wrong pattern can silently corrupt a file. Always preview changes first:

# Preview - prints changes to terminal without modifying the file
sed 's/old/new/g' config.conf

# Apply with backup - creates config.conf.bak before writing
sed -i.bak 's/old/new/g' config.conf

Verify: Compare the backup and modified file to confirm only the intended changes were made:

diff config.conf.bak config.conf

6. Using sed on Binary Files

sed is designed for text files. Using it on binary files, such as images or executables, can corrupt them silently. If you accidentally run sed -i against a binary, the file may become unusable with no error message.

Fix: Use the file command to check a file’s type before editing, and use tools such as xxd or hexedit for binary file manipulation:

file myapp
myapp: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked

Combine sed with Other Text-Processing Commands

The sed command works well on its own, but combining it with other Linux text-processing commands extends its reach. Here are complementary tools with practical examples:

  • grep: Search for patterns in files and filter text before or after sed processing. Example: grep -rIlZ --include="*.log" "ERROR" ./logs | xargs -0 -r sed -i.bak 's/ERROR/WARN/g' finds only matching log files (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: tr -d '\r' < config.ini | 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 -c strips leading whitespace, sorts lines, and counts duplicates.
  • tail command: 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.
  • split command: Break large files into smaller chunks for parallel sed processing. Example: split -l 10000 large.log chunk_ && for f in chunk_*; do sed -i.bak 's/old/new/g' "$f"; done splits a log file and applies replacements to each chunk.

Combining these commands with sed gives scripts a practical path from filtering to replacement to post-processing without turning every task into a custom program.

Conclusion: Use sed Safely for Text Replacement

sed is ready for quick, previewed replacements, from single-file substitutions to guarded recursive edits. Keep -i.bak for risky changes, check GNU-specific features before sharing scripts across systems, and move to broader sed command examples when the task shifts beyond find-and-replace work.

Share this guide

Help another Linux user troubleshoot faster

Share this guide with someone troubleshooting Linux systems or saving it for later.

Follow LinuxCapable

Want more LinuxCapable guides in Google?

Add LinuxCapable as a preferred source so Google can show more of our fresh Linux tutorials in Top Stories and From your sources when relevant.

Add LinuxCapable as a preferred source on Google
Search LinuxCapable

Need another guide?

Search LinuxCapable for package installs, commands, troubleshooting, and follow-up guides related to what you just read.

Found this guide useful?

Support LinuxCapable to keep tutorials free and up to date.

Buy me a coffeeBuy me a coffee
Before commenting, please review our Comments Policy.
Formatting tips for your comment

You can use basic HTML to format your comment. Useful tags currently allowed in published comments:

You type Result
<code>command</code> command
<strong>bold</strong> bold
<em>italic</em> italic
<blockquote>quote</blockquote> quote block

Got a Question or Feedback?

We read and reply to every comment - let us know how we can help or improve this guide.

Verify before posting: