The sed Command Explained
sed, short for stream editor, is one of the oldest and most widely used text-processing tools on Linux. It reads input line by line, applies a set of editing commands, and writes the transformed result to standard output. Unlike a text editor, there is no interactive session: you specify what you want changed, and sed does it in one pass. That makes it ideal for scripting, automated file editing, and quick command-line find-and-replace jobs.
This guide covers the substitution command (the one you will use most), addressing specific lines, deleting text, and the common pitfalls that trip up newcomers.
Basic substitution
The core sed operation is substitution, using the s command:
sed 's/old/new/' file.txt
This reads file.txt, replaces the first occurrence of old with new on each line, and prints the result to standard output. The original file is untouched unless you add the -i flag (covered below).
echo "The quick brown fox" | sed 's/quick/slow/'
# Output: The slow brown fox
The global flag
By default, sed only replaces the first match on each line. To replace every match, add g:
echo "one two two three two" | sed 's/two/2/g'
# Output: one 2 2 three 2
echo "one two two three two" | sed 's/two/2/'
# Output: one 2 two three two (only the first match changed)
Forgetting the g flag is one of the most common sources of confusion when starting out with sed.
Case-insensitive matching
Add the I flag to match regardless of case:
echo "Error: ERROR: error" | sed 's/error/warning/gI'
# Output: warning: warning: warning
Editing files in place
By default sed only prints its output, it never modifies the source file. To edit the file directly, use -i:
sed -i 's/old/new/g' file.txt
This is a destructive operation with no confirmation prompt, so it is good practice to run the command without -i first to review the output, then add -i once you are confident it is correct. To keep an automatic backup of the original, append a suffix to -i:
sed -i.bak 's/old/new/g' file.txt
This saves the original content as file.txt.bak before applying the change to file.txt.
Addressing specific lines
sed commands can be restricted to specific lines using an address before the command.
By line number
sed '3d' file.txt # delete line 3
sed '2,5d' file.txt # delete lines 2 through 5
sed '3s/old/new/' file.txt # substitute only on line 3
By pattern
sed '/^#/d' file.txt # delete lines starting with #
sed '/pattern/s/old/new/' file.txt # substitute only on lines matching pattern
By range between two patterns
sed '/START/,/END/d' file.txt
This deletes everything from the first line matching START through the first subsequent line matching END, inclusive, useful for stripping a known block of text such as a commented-out configuration section.
Deleting lines
The d command deletes matching lines entirely rather than transforming them:
sed '/^$/d' file.txt # delete blank lines
sed '/^#/d' file.txt # delete comment lines starting with #
sed '5,10d' file.txt # delete lines 5 through 10
A frequent real-world combination is stripping both comments and blank lines from a configuration file to see only the active settings:
sed '/^#/d; /^$/d' config.conf
Multiple commands separated by a semicolon are applied in sequence to each line.
Inserting and appending text
sed '3i\Inserted before line 3' file.txt # insert text before line 3
sed '3a\Appended after line 3' file.txt # append text after line 3
These are less commonly needed than substitution and deletion, but useful for programmatically adding headers, footers, or markers to a file.
Regular expressions in sed
By default, sed uses basic regular expressions (BRE), where characters like +, ?, |, and () need a backslash to be treated as special:
sed 's/[0-9]\+/NUMBER/g' file.txt
GNU sed’s -E flag switches to extended regular expressions (ERE), which is closer to the regex syntax most people are used to from grep -E:
sed -E 's/[0-9]+/NUMBER/g' file.txt
Capture groups
Parentheses capture part of the match for reuse in the replacement, referenced as \1, \2, and so on:
echo "John Smith" | sed -E 's/([A-Za-z]+) ([A-Za-z]+)/\2, \1/'
# Output: Smith, John
This swaps first and last name by capturing each word into a numbered group and reordering them in the replacement.
Using a different delimiter
The forward slash is the conventional delimiter for s/old/new/, but it is not required. If the pattern itself contains slashes, such as a file path, using a different delimiter avoids a wall of escaped slashes:
sed 's/old/new/' file.txt # default delimiter
sed 's|/usr/local|/opt|' file.txt # pipe delimiter, cleaner for paths
sed 's#/var/log#/mnt/logs#' file.txt # hash delimiter, same idea
Any character can act as the delimiter as long as it is used consistently across all three parts of the substitution.
Common real-world one-liners
# Replace all tabs with spaces
sed 's/\t/ /g' file.txt
# Remove trailing whitespace from every line
sed 's/[ \t]*$//' file.txt
# Add a prefix to every line
sed 's/^/PREFIX: /' file.txt
# Print only lines 10 through 20 (like a targeted head/tail combo)
sed -n '10,20p' file.txt
# Replace a value in multiple files at once, editing each in place
sed -i 's/old-hostname/new-hostname/g' /etc/hosts /etc/hostname
The -n flag combined with p in that second-to-last example suppresses sed’s default behavior of printing every line, so only the explicitly printed lines (10 through 20 here) appear in the output.
sed vs awk vs grep
These three tools overlap but serve different primary purposes. grep finds and prints matching lines without modifying them. sed transforms text line by line, primarily for substitution and deletion. awk is built around fields and columns, better suited when you need to extract, rearrange, or compute across specific columns of structured text rather than operate on whole lines. In practice, many shell pipelines chain all three together: grep to filter, sed to clean up formatting, awk to extract a specific field.
Frequently Asked Questions
What does sed stand for and what is it used for?
sed stands for stream editor. It reads text line by line, applies editing commands you specify, and writes the result to standard output, without opening an interactive editor. It is most commonly used for find-and-replace operations, deleting matching lines, and other line-based text transformations, either on the command line directly or inside shell scripts that need to modify text files automatically.
How do I edit a file in place with sed instead of just printing the result?
Add the -i flag: sed -i “s/old/new/g” file.txt modifies file.txt directly. On macOS and BSD systems, -i requires an argument (even an empty one) for the backup suffix, but on Linux with GNU sed, -i alone works and modifies the file with no backup. To keep a backup automatically, use -i.bak, which saves the original as file.txt.bak before overwriting file.txt. Without -i, sed only prints the transformed text to standard output and leaves the original file untouched, which is the safer default for testing a command before committing to it.
What is the difference between sed and grep?
grep searches for lines matching a pattern and prints those matching lines (or optionally the non-matching ones with -v); it does not modify text. sed can search for patterns too, but its purpose is transformation: replacing text, deleting matching lines, inserting text, and more. A common workflow combines them: grep to find which files or lines contain something, sed to actually change it. For quick filtering with no modification, use grep. For any kind of automated editing, sed is the tool.
How do I use sed to delete lines matching a pattern?
Use the d command with an address: sed “/pattern/d” file.txt prints file.txt with every line matching pattern removed. To delete by line number instead of pattern, use sed “5d” file.txt to delete line 5, or sed “2,4d” file.txt to delete lines 2 through 4. Combine with -i to make the deletion permanent: sed -i “/pattern/d” file.txt. As with any in-place edit, it is worth running the command without -i first to confirm the output looks correct before overwriting the original file.
Why does my sed substitution only replace the first match on each line?
By default, sed replaces only the first occurrence of the pattern on each line. To replace every occurrence on every line, add the g (global) flag at the end of the substitution: sed “s/old/new/g” file.txt. Without g, sed “s/old/new/” file.txt only touches the first old on each line, leaving any additional occurrences on the same line unchanged, which is a very common source of confusion for people new to sed.
Can sed use regular expressions?
Yes, sed uses basic regular expressions (BRE) by default, where characters like + and ? need to be escaped with a backslash to have their special meaning. GNU sed also supports extended regular expressions (ERE), closer to what tools like grep -E or egrep use, by adding the -E flag (or -r on some systems): sed -E “s/[0-9]+/NUMBER/g” file.txt matches one or more digits without needing to escape the plus sign. If a pattern involving +, ?, |, or () is not matching as expected, check whether -E is needed for the regex syntax you are writing.