How to Use sed to Find and Replace Strings in Files

By 

Updated on

7 min read

Using the sed command to find and replace strings in a Linux file

When working with text files, you will often need to find and replace strings of text in one or more files.

sed is a stream editor. It can perform basic text manipulation on files and input streams such as pipelines. With sed, you can search, find and replace, insert, and delete words and lines. It supports basic and extended regular expressions that allow you to match complex patterns.

This guide explains how to use sed to find and replace strings in files, covering the most common options, flags, and patterns.

To preview a find-and-replace operation before changing the file, use the s (substitute) command without -i:

Terminal
sed 's/old-string/new-string/g' file.txt

This prints the edited content to the terminal without modifying file.txt. When the output looks correct, add -i.bak to edit the file in place and keep a backup, or use -i if you do not need one.

Find and Replace Strings with sed

There are several versions of sed, with some functional differences between them. macOS uses the BSD version, while most Linux distributions come with GNU sed pre-installed by default. The examples in this guide use GNU sed.

The general syntax for searching and replacing text with sed is:

txt
sed -i 's/SEARCH_REGEX/REPLACEMENT/g' INPUTFILE
  • -i - By default, sed writes output to standard output. This option tells sed to edit the file in place. If an extension is supplied (for example -i.bak), a backup of the original file is created.
  • s - The substitute command, the most commonly used sed command.
  • / / / - Delimiter character. It can be any character, but / is the most common choice.
  • SEARCH_REGEX - A plain string or regular expression to search for.
  • REPLACEMENT - The replacement string.
  • g - Global replacement flag. By default, sed replaces only the first match on each line. When this flag is set, all matches are replaced.
  • INPUTFILE - The name of the file to operate on.

It is good practice to quote the expression so that shell meta-characters are not expanded.

For demonstration purposes, the examples below use the following file:

file.txttxt
123 Foo foo foo
foo /bin/bash Ubuntu foobar 456

If the g flag is omitted, only the first match on each line is replaced:

Terminal
sed -i 's/foo/linux/' file.txt
output
123 Foo linux foo
linux /bin/bash Ubuntu foobar 456

With the global replacement flag, sed replaces all occurrences of the search pattern:

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

Notice that the substring foo inside foobar is also replaced. To match only whole words and avoid partial matches, use the word-boundary expression \b at both ends of the search string:

Terminal
sed -i 's/\bfoo\b/linux/g' file.txt
output
123 Foo linux linux
linux /bin/bash Ubuntu foobar 456

To make the pattern case-insensitive, use the I flag. The following example uses both g and I:

Terminal
sed -i 's/foo/linux/gI' file.txt
output
123 linux linux linux
linux /bin/bash Ubuntu linuxbar 456

If the search string contains the delimiter character (/), escape each slash with a backslash. For example, to replace /bin/bash with /usr/bin/zsh:

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

A cleaner approach is to use a different delimiter such as | or ::

Terminal
sed -i 's|/bin/bash|/usr/bin/zsh|g' file.txt
output
123 Foo foo foo
foo /usr/bin/zsh Ubuntu foobar 456

sed also supports regular expressions. To replace all 3-digit numbers with the string number, run:

Terminal
sed -i 's/\b[0-9]\{3\}\b/number/g' file.txt
output
number Foo foo foo
foo /bin/bash Ubuntu foobar number

The ampersand character & represents the matched pattern and can be used in the replacement string. For example, to wrap each 3-digit number in curly braces:

Terminal
sed -i 's/\b[0-9]\{3\}\b/{&}/g' file.txt
output
{123} Foo foo foo
foo /bin/bash Ubuntu foobar {456}

It is always a good idea to create a backup before editing a file in place. To do this, provide a backup extension to the -i option. The following command edits file.txt and saves the original as file.txt.bak:

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

To confirm the backup was created, list the files with ls :

Terminal
ls
output
file.txt  file.txt.bak

Preview Changes Without Modifying the File

Before running sed with the -i flag, it is good practice to preview the result first. Omitting -i sends the output to standard output without changing the file:

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

The original file remains unchanged. Once the output looks correct, add -i to apply the changes.

Replace Text on a Specific Line

To limit a substitution to a specific line number, place the line address before the s command:

Terminal
sed '2s/foo/linux/' file.txt
output
123 Foo foo foo
linux /bin/bash Ubuntu foobar 456

To apply the replacement across a range of lines, use start,end before the s command:

Terminal
sed '1,2s/foo/linux/g' file.txt
output
123 Foo linux linux
linux /bin/bash Ubuntu linuxbar 456

Replace the Nth Occurrence

By default, sed replaces the first match on each line. To replace only the Nth match, pass the occurrence number as a flag. For example, to replace only the second occurrence of foo per line:

Terminal
sed 's/foo/linux/2' file.txt
output
123 Foo foo linux
foo /bin/bash Ubuntu foobar 456

To replace all occurrences starting from the Nth, combine the occurrence number with the g flag:

Terminal
sed 's/foo/linux/2g' file.txt
output
123 Foo foo linux linux
foo /bin/bash Ubuntu foobar 456

Recursive Find and Replace

To recursively replace a string across all files in a directory, combine sed with find or grep .

The following command searches all files in the current working directory and passes them to sed:

Terminal
find . -type f -exec sed -i 's/foo/bar/g' {} +

To handle filenames that contain spaces, use the -print0 option with xargs -0 :

Terminal
find . -type f -print0 | xargs -0 sed -i 's/foo/bar/g'

To limit the replacement to files with a specific extension:

Terminal
find . -type f -name "*.md" -print0 | xargs -0 sed -i 's/foo/bar/g'

To exclude hidden directories and files starting with a dot:

Terminal
find . -type f -not -path '*/\.*' -print0 | xargs -0 sed -i 's/foo/bar/g'

To replace only in files that actually contain the search string, use grep to filter first:

Terminal
grep -rlZ 'foo' . | xargs -0 sed -i.bak 's/foo/bar/g'

Quick Reference

For a printable quick reference, see the Sed cheatsheet .

Option / FlagDescription
s/SEARCH/REPLACE/Replace first match per line
s/SEARCH/REPLACE/gReplace all matches (global)
s/SEARCH/REPLACE/ICase-insensitive match
s/SEARCH/REPLACE/2Replace only the 2nd occurrence per line
s/SEARCH/REPLACE/2gReplace from the 2nd occurrence onwards
\bWord boundary, prevents partial word matches
&Reference to the matched pattern in replacement
-iEdit file in place
-i.bakEdit in place and save backup with .bak extension
Ns/.../.../Limit substitution to line N
N,Ms/.../.../Limit substitution to lines N through M

Troubleshooting

sed: 1: "file.txt": undefined label on macOS
macOS ships with BSD sed, which requires an explicit extension or an empty string when using -i. On macOS, run sed -i '' 's/foo/bar/g' file.txt instead of sed -i 's/foo/bar/g' file.txt.

Pattern matches more than expected
Special regex characters such as ., *, [, and \ have special meaning in sed patterns. Escape them with a backslash if you want to match them literally. For example, to match a literal dot use \. instead of ..

No matches found despite the string being present
Check the delimiter character. If the search string contains /, either escape each slash with \ or switch to a different delimiter such as | or :. Also verify the file encoding; sed may not handle non-UTF-8 files as expected.

FAQ

How do I preview sed changes without modifying the file?
Run sed without the -i flag. The result is written to standard output and the original file is left unchanged.

Why does sed -i not work on macOS?
macOS uses BSD sed, which requires either a backup extension or an empty string after -i: sed -i '' 's/foo/bar/g' file.txt. On Linux, GNU sed accepts -i without an argument.

How do I replace a string that contains forward slashes?
Use a different delimiter character such as | or :. For example: sed 's|/bin/bash|/usr/bin/zsh|g' file.txt.

How do I replace text only on lines that match a pattern?
Use a regex address before the substitute command: sed '/pattern/s/foo/bar/g' file.txt. This applies the substitution only to lines containing pattern.

Conclusion

sed is a powerful tool for finding and replacing strings in files directly from the command line. Use the g flag for global replacement, \b for word boundaries, and -i.bak to keep a backup before modifying files in place. Always test your expression first by omitting -i to preview the output before committing changes.

Linuxize Weekly Newsletter

A quick weekly roundup of new tutorials, news, and tips.

About the authors

Dejan Panovski

Dejan Panovski

Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 800+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.

View author page