The sed command in Linux turns repetitive text edits into repeatable terminal commands. It reads files or pipeline input line by line, applies the editing rules you provide, and prints the result without opening an interactive editor, which makes it useful for logs, configuration snippets, deployment templates, and quick data cleanup.
Most examples use GNU sed, the implementation shipped by mainstream Linux distributions. The broader command surface includes printing, deletion, insertion, address ranges, multi-line editing, hold space, script files, and practical pipelines; deeper substitution-only coverage belongs in the sed find and replace guide.
Understand the sed Command in Linux
Sed works as a stream editor: it loads one input line into a working buffer, applies the script you gave it, then prints the result unless you suppress automatic output. That model explains why sed fits both one-off shell commands and repeatable scripts.
- System administrators extract targeted log entries, filter configuration snippets, renumber documentation, and preview bulk edits before writing changes.
- Developers wire
sedinto build pipelines to inject version strings, strip comments before deployment, or reshape configuration templates during packaging. - Data analysts chain
sedwith other CLI tools to clean CSV exports, normalize delimiters, and isolate fields without reaching for heavier scripting languages.
The official GNU sed manual is the best reference when you need full command semantics. Start with Linux command usage patterns that are easy to test with disposable files before moving the same pattern into real automation.
Basic Syntax
The basic syntax follows this pattern:
sed [OPTIONS] 'COMMAND' [INPUT-FILE]
Breaking down each component:
- OPTIONS: Flags that modify
sedbehavior, such as-ifor in-place editing,-nfor suppressing automatic output, or-Efor extended regular expressions. These are optional and can be combined, such as-n -E. - COMMAND: The transformation you want to apply, wrapped in single quotes to protect it from shell interpretation. Commands can be simple like
'd'to delete lines, or complex like's/old/new/g'for global substitution. You can chain multiple commands with semicolons:'s/foo/bar/; /error/d'. - INPUT-FILE: The file to process. If omitted,
sedreads from standard input, so you can pipe data from another command with a pattern such asprintf 'foo\n' | sed 's/foo/bar/'.
How sed Processes Text
Sed operates using two buffers that determine how text flows through the editor:
- Pattern space: The working buffer where sed stores the current line being processed. Every sed command you write operates on the pattern space by default. When sed reads a new line, it replaces the pattern space content with that line (unless you use commands like
Nthat append to it). - Hold space: A secondary storage buffer that persists between lines. You can copy or exchange data between pattern space and hold space using commands like
h(hold),g(get), andx(exchange). This enables complex operations like reversing files, accumulating data across lines, or implementing conditional logic.
How sed Processes Each Line
The typical sed cycle works like this:
- Read a line from input into the pattern space
- Execute commands on the pattern space (substitute, delete, transform, etc.)
- Print the pattern space (unless
-nsuppresses it or a command deletes it) - Move to the next line and repeat
For instance, sed 's/Linux/Unix/' file.txt reads file.txt line by line, replaces the first occurrence of “Linux” with “Unix” on each line, and prints the result to your terminal without changing the original file. The pattern space holds one line at a time, the substitution command modifies it, and sed automatically prints the modified line before moving to the next input line.
Use these quick reference tables to choose the right command family before moving into full examples.
sed Command Quick Reference
Text Substitution
| Task | Option/Command | What It Does |
|---|---|---|
| Replace first match per line | s/pattern/replacement/ | Substitutes the first occurrence of “pattern” with “replacement” on each line |
| Replace all matches on each line | s/pattern/replacement/g | The g flag makes substitution global, replacing every occurrence |
Deletion Operations
| Task | Option/Command | What It Does |
|---|---|---|
| Delete matching lines | /pattern/d | Removes entire lines that contain “pattern” |
| Delete specific line numbers | '3d' or '5,10d' | Deletes line 3 or lines 5 through 10 |
| Delete blank lines | '/^$/d' | Removes all empty lines from output |
Printing and Output Control
| Task | Option/Command | What It Does |
|---|---|---|
| Print specific lines | -n '5p' or -n '10,20p' | Prints only line 5 or lines 10 through 20 (requires -n flag) |
| Print matching lines | -n '/pattern/p' | Shows only lines containing “pattern” (similar to grep) |
| Suppress automatic output | -n | Only prints lines when explicitly told with the p command |
Insert and Append
| Task | Option/Command | What It Does |
|---|---|---|
| Insert text before a line | /pattern/i\text | Inserts “text” before lines matching “pattern” |
| Append text after a line | /pattern/a\text | Appends “text” after lines matching “pattern” |
Line Addressing
| Task | Option/Command | What It Does |
|---|---|---|
| Apply to specific line | '5s/old/new/' | Substitutes only on line 5 |
| Apply to range | '10,20s/old/new/' | Substitutes on lines 10 through 20 |
| Apply to pattern range | '/start/,/end/d' | Deletes lines from first “start” match to first “end” match |
| Negate address | '/pattern/!d' | Deletes all lines not matching “pattern” |
Multi-line Operations
| Task | Option/Command | What It Does |
|---|---|---|
| Append next line to pattern space | N | Reads next line and appends to current pattern space with newline |
| Print first line of pattern space | P | Prints up to first newline in pattern space (useful with N) |
| Delete first line of pattern space | D | Deletes up to first newline and restarts the cycle without reading a new line |
Hold Space Operations
| Task | Option/Command | What It Does |
|---|---|---|
| Copy pattern space to hold space | h | Overwrites hold space with pattern space content |
| Append pattern space to hold space | H | Appends pattern space to hold space with newline separator |
| Copy hold space to pattern space | g | Overwrites pattern space with hold space content |
| Append hold space to pattern space | G | Appends hold space to pattern space with newline separator |
| Exchange buffers | x | Swaps pattern space and hold space contents |
File Operations
| Task | Option/Command | What It Does |
|---|---|---|
| Edit files in place | -i | Modifies the original file instead of printing to stdout |
| Read file and insert | r filename | Reads content from a file and inserts it after the current line |
| Write to file | w filename | Writes pattern space to a file (appends if the file exists) |
| Use script file | -f script.sed | Reads sed commands from a file instead of the command line |
Advanced Features
| Task | Option/Command | What It Does |
|---|---|---|
| Chain multiple commands | -e 'cmd1' -e 'cmd2' | Applies multiple transformations in sequence |
| Use extended regex | -E | Enables extended regular expressions (less escaping needed) |
| Quit processing | q | Exits sed immediately after the current line |
| Transform characters | y/abc/xyz/ | Transliterates characters (similar to the tr command) |
| Print line numbers | = | Prints the current line number before the line content |
The -n option suppresses automatic output. Normally, sed prints every input line whether it changed or not; with -n, only explicit print commands such as p produce output.
Verify or Install sed on Linux
GNU sed ships with virtually every mainstream Linux distribution, so normal desktop and server installs usually need only a quick availability check. Minimal containers, rescue images, and BusyBox-based systems may provide a smaller implementation or omit the full GNU package.
Check whether sed is already present:
command -v sed
A normal Linux system returns a path similar to this:
/usr/bin/sed
Confirm GNU sed with the version banner:
sed --version | head -1
GNU sed output typically looks like this:
sed (GNU sed) 4.9
If the command is not found, use your distribution’s package manager. Avoid removing sed from normal systems because many base packages and scripts assume it exists.
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
These commands install the distribution’s sed package when the command is missing. On Alpine, minimal images often expose BusyBox sed first; installing the sed package provides GNU sed behavior for the command patterns in the examples.
Basic sed Command Examples
Example 1: Basic Text Substitution
Text substitution is sed’s most recognized operation, though far from its only capability. This example demonstrates the simplest form before moving to sed’s broader feature set:
echo "Welcome to Linux" | sed 's/Linux/Unix/'
Output:
Welcome to Unix
When the search or replacement contains forward slashes, use a different delimiter so the command stays readable, such as sed 's|/var/log|/srv/log|g' file.txt. Keep deeper substitution work, including global replacement, case-insensitive matching, delimiter choices, and in-place backups, in the dedicated find-and-replace workflow rather than expanding the general command reference.
Example 2: Printing Specific Lines
Additionally, the -n option combined with the p command lets you extract specific lines without modifying them. This is useful when you need to view particular sections of log files, configuration files, or data exports.
First, display line 5 from a sample log:
sed -n '5p' application.log
Next, pull lines 10 through 20 from a data file:
sed -n '10,20p' data.txt
Finally, show lines matching a pattern (similar to grep):
sed -n '/error/p' application.log
The -n flag suppresses sed’s default behavior of printing every line, so only lines explicitly marked with p appear in the output. Without -n, you would see all lines plus duplicates of the matched ones.
Example 3: Deleting Lines
In practice, when processing log files or data exports, you often need to remove lines matching specific patterns. Sed’s d command deletes lines from the output stream without modifying the source file.
To start, remove every line containing “debug”:
sed '/debug/d' application.log
Then clear any blank lines:
sed '/^$/d' messy-file.txt
After that, drop lines 5 through 10:
sed '5,10d' data.csv
Finally, cut everything from a specific marker to the end of the file:
sed '/START_OF_FOOTER/,$d' document.txt
The d command removes matched lines from the pattern space entirely, preventing them from reaching the output. The dollar sign ($) in address ranges represents the last line of the input.
Example 4: Inserting and Appending Text
Similarly, adding lines before or after specific patterns lets you inject headers into data files, add comments to configuration sections, or insert timestamps without manually editing each file.
Insert text before a pattern:
sed '/^database_settings/i\# Database Configuration' config.ini
Append text after a pattern:
sed '/^server {$/a\ # Server block configuration' nginx.conf
Insert multiple lines (using literal newlines):
sed '/pattern/i\First line\
Second line\
Third line' file.txt
The i command inserts before the matched line, while a appends after it. Both commands place the new text in the output stream without modifying the pattern space content of existing lines.
Example 5: Changing Text Case with Transform
Likewise, the y command transliterates characters, similar to the tr command. This is useful when normalizing data for comparisons, standardizing input formats, or preparing text for case-sensitive systems.
Convert lowercase to uppercase:
echo "hello world" | sed 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'
Output:
HELLO WORLD
Convert specific characters:
echo "a-b-c-d" | sed 'y/-/_/'
Output:
a_b_c_d
The y command maps each character in the first set to the corresponding character in the second set. Both sets must contain the same number of characters, and the transformation applies to every matching character in the pattern space.
Example 6: Printing Line Numbers
Similarly, the = command prints the current line number, which helps when debugging sed scripts, identifying line positions in large files, or creating numbered lists.
Print line numbers for all lines:
printf "apple\nbanana\ncherry\n" | sed '='
Output:
1 apple 2 banana 3 cherry
Print line numbers only for matching lines:
sed -n '/error/=' application.log
The = command outputs the line number on its own line before the pattern space content, so you see the number followed by the actual text on the next line.
Advanced sed Command Examples
Example 7: Address Ranges and Line Selection
Moreover, sed’s addressing system lets you apply commands to specific lines, ranges of lines, or lines matching patterns. This precision is essential when editing configuration files where changes should only affect particular sections, or when processing log files where you need to extract or modify specific time ranges.
Target a specific line number
sed '3s/old/new/' file.txt
Operate on a range of line numbers
sed '10,20s/DEBUG/INFO/' application.log
Match a range defined by two patterns
sed '/<configuration>/,/<\/configuration>/s/enabled="false"/enabled="true"/' config.xml
Process from a specific line to end of file
sed '100,$d' large-file.txt
Negate an address
sed '/^#/!d' script.sh
This last example keeps only comment lines (those starting with #) by deleting everything else. The exclamation mark negates the address, so the delete command applies to all lines that don’t match the pattern.
Example 8: Multi-line Operations
Additionally, multi-line commands let you work with blocks of text instead of individual lines. This is crucial when processing data formats where logical units span multiple lines, such as configuration blocks, code functions, or data records split across lines.
Join lines into a single record
printf "line one\nline two\nline three\n" | sed 'N;s/\n/ /'
Output:
line one line two line three
The N command appends the next line to the pattern space with a newline separator, then the substitution replaces that newline with a space. Sed processes pairs of lines this way, joining every two consecutive lines.
Collapse multiple blank lines
printf "one\n\n\ntwo\n\n\nthree\n" | sed '/^$/N;/^\n$/D'
Output:
one two three
The uppercase D command deletes only the first line in the multi-line pattern space and restarts the cycle, so repeated blank lines are reduced to a single separator.
Match patterns across line boundaries
printf "Error:\nConnection timeout\n" | sed 'N;s/Error:\nConnection/Error: Network connection/'
Output:
Error: Network connection timeout
Multi-line operations are particularly useful when reformatting code, merging continued lines in configuration files, or processing data exports where field values span multiple lines.
Example 9: Hold Space and Pattern Space
Furthermore, the hold space acts as a secondary buffer for storing data between lines. This enables complex transformations like reversing file order, accumulating data across multiple lines, or implementing conditional logic based on previous content.
Reverse the order of lines
printf "first\nsecond\nthird\n" | sed -n '1!G;h;$p'
Output:
third second first
This approach works by: (1) For all lines except the first, append hold space to pattern space with G, (2) Copy pattern space to hold space with h, (3) On the last line ($), print the accumulated result. Each new line gets prepended to the accumulated content in hold space, effectively reversing the order.
Detect consecutive duplicates
printf "apple\napple\nbanana\nbanana\nbanana\ncherry\n" | sed -n 'N;/^\(.*\)\n\1$/p;D'
The command reads two lines at a time, prints them when both lines match, and restarts the cycle so you only see consecutive duplicates once per pair.
Swap every two lines
printf "line1\nline2\nline3\nline4\n" | sed 'N;s/\(.*\)\n\(.*\)/\2\n\1/'
Output:
line2 line1 line4 line3
Hold space operations become essential when you need to maintain state across lines, such as tracking section headers, accumulating totals, or comparing current lines with previous ones.
Example 10: Reading and Writing Files
Additionally, sed can read content from external files and insert it into the output stream, or write portions of the pattern space to separate files. This enables powerful workflows like merging templates with data, splitting files based on patterns, or building files dynamically during processing.
Insert file content after matching lines
echo "This is a header." > header.txt
printf "Section 1\nContent here\nSection 2\nMore content\n" | sed '/^Section/r header.txt'
Output:
Section 1 This is a header. Content here Section 2 This is a header. More content
The r command reads the entire file and inserts it after each line matching the pattern. This is useful for injecting common headers, footers, or template content at specific points.
Write matching lines to a separate file
sed -n '/ERROR/w errors.log' application.log
Split a file based on patterns
sed '/^INFO/w info.log
/^WARN/w warnings.log
/^ERROR/w errors.log' mixed.log
The w command appends the pattern space to the specified file. If the file doesn’t exist, sed creates it; if it exists, sed appends to it. This lets you filter and route different parts of input to different destinations in a single pass.
Example 11: Using Sed Script Files
Whenever sed commands become complex or you need to reuse the same transformations across multiple files, putting commands in a script file makes them easier to maintain and share. The -f option reads commands from a file instead of the command line.
Create a sed script file:
cat > cleanup.sed <<'EOF'
# Remove blank lines
/^$/d
# Remove comments
/^#/d
# Convert tabs to spaces
s/\t/ /g
# Trim trailing whitespace
s/[[:space:]]\+$//
EOF
Apply the script to a file:
sed -f cleanup.sed messy-config.txt
Script files support comments (lines starting with #) and can contain as many commands as needed, one per line. Commands in script files execute in sequence, just as if you chained them with semicolons on the command line.
Apply the same script to multiple files:
The next command edits files in place and writes backup copies with a
.baksuffix. Preview the transformed output first so you can confirm the scope before modifying files.
Preview the result without changing files:
find . -name "*.conf" -exec sed -f cleanup.sed {} +
After reviewing the preview output, apply the edits in place with backups:
find . -name "*.conf" -exec sed -i.bak -f cleanup.sed {} +
This approach keeps your transformation logic in one place, making it easier to version control, document, and apply consistently across projects.
Example 12: Conditional Execution and Branching
Similarly, sed supports conditional execution using the b (branch) and t (test) commands. These let you create complex logic flows within sed scripts, implementing if-then-else patterns or loops without invoking a full scripting language.
Skip processing for comment lines:
sed '/^#/b; s/old/new/g' config.txt
This branches (jumps to the end of the script) for lines starting with #, effectively skipping the substitution command for comments.
Apply multiple substitutions until no more changes occur:
echo "aaabbbccc" | sed ':loop; s/aa/a/g; t loop'
Output:
abbbccc
The :loop creates a label, and t loop branches back to that label if the previous substitution succeeded. This creates a loop that keeps replacing aa with a until no more aa sequences exist.
Example 13: Quitting Early with q
In turn, the q command exits sed immediately after processing the current line. This improves performance when you only need to process the beginning of large files, such as extracting headers or stopping after finding a specific pattern.
Print only the first 10 lines (like head -10):
sed '10q' large-logfile.log
Stop processing after finding a pattern:
sed '/^ERROR/q' application.log
Extract everything up to a marker:
sed '/^---END OF HEADER---$/q' document.txt
The q command prints the current line (unless you use -n) and then exits immediately, saving time on large files by avoiding unnecessary processing of remaining content.
Practical sed Workflows
Example 14: Processing Log Files
Because log file analysis often requires extracting specific entries, removing noise, or reformatting timestamps, sed handles these tasks efficiently without loading entire files into memory.
Begin by extracting only error and warning messages:
sed -n -E '/ERROR|WARN/p' application.log
Next, remove debug and trace messages:
sed -E '/DEBUG|TRACE/d' verbose.log > clean.log
Then isolate logs from a specific time range:
sed -n '/2025-11-06 14:00/,/2025-11-06 15:00/p' timestamped.log
Finally, add line numbers to error messages for easier debugging:
sed -n '/ERROR/{=;p;}' application.log | sed 'N;s/\n/: /'
Example 15: CSV and Data File Manipulation
Likewise, sed excels at cleaning and transforming CSV files or other delimited data formats. You can extract columns, reorder fields, or normalize inconsistent formatting without loading data into spreadsheet software.
Extract the second column from CSV data:
printf "Name,Age,City\nJohn,30,NYC\nJane,25,LA\n" | sed 's/^[^,]*,\([^,]*\).*/\1/'
Output:
Age 30 25
Remove the header row from CSV:
sed '1d' data.csv > data-no-header.csv
Convert comma-separated to tab-separated:
sed 's/,/\t/g' data.csv > data.tsv
Remove quotes from quoted CSV fields:
sed 's/"//g' quoted.csv > unquoted.csv
Example 16: Configuration File Updates
For operations teams, automated configuration management relies on tools like sed to modify settings without manual editing. This is especially valuable when provisioning servers, updating application settings during deployment, or maintaining consistent configurations across environments.
The following examples preview each change before using
sed -i.bak, which edits the file in place and keeps a backup with a.baksuffix. Keep separate backups for production configuration files.
Change a configuration value:
sed 's/^max_connections = .*/max_connections = 200/' postgresql.conf
sudo sed -i.bak 's/^max_connections = .*/max_connections = 200/' postgresql.conf
Enable a commented-out setting:
sed 's/^# *\(listen_addresses\)/\1/' postgresql.conf
sudo sed -i.bak 's/^# *\(listen_addresses\)/\1/' postgresql.conf
Update multiple related settings in one pass:
sed -e 's/old_server/new_server/' \
-e 's/port=3306/port=3307/' \
-e 's/timeout=30/timeout=60/' database.ini
sudo sed -i.bak -e 's/old_server/new_server/' \
-e 's/port=3306/port=3307/' \
-e 's/timeout=30/timeout=60/' database.ini
Add a new setting after a specific section header:
sed '/^\[database\]$/a\new_option = value' config.ini
sudo sed -i.bak '/^\[database\]$/a\new_option = value' config.ini
Example 17: Code and Documentation Processing
On macOS or other BSD-based systems,
sed -iexpects a backup suffix. Usesed -i '' 's/pattern/replacement/' fileto edit in place without leaving backup files, or provide an explicit suffix such as-i .bak.
Developers frequently use sed in build pipelines to inject version strings, strip comments for production code, or transform documentation formats. These operations integrate seamlessly into automated workflows.
Strip single-line comments from code:
sed '/^[[:space:]]*\/\//d' source.js > clean-no-comments.js
This removes standalone // comment lines without touching URLs or other inline content, which is safer for source files that embed strings like https://.
Trim trailing inline comments that follow code (assuming your style inserts a space before the comment):
sed -E 's#[[:space:]]+//.*$##' source.js > clean-inline-comments.js
This expression only removes // sequences that are preceded by whitespace, so strings and protocol prefixes stay intact. Adjust the pattern if your codebase formats inline comments differently.
Inject build version into source files:
This workflow performs an in-place edit on
version.h. Review the preview output first so you can confirm the replacement before writing changes, and keep a backup suffix while testing.
VERSION="2.4.1"
sed "s/VERSION_PLACEHOLDER/$VERSION/" version.h
sed -i.bak "s/VERSION_PLACEHOLDER/$VERSION/" version.h
Convert Markdown headers to HTML:
sed -E 's/^## (.*)$/<h2>\1<\/h2>/' document.md
Extract function definitions from source code:
sed -n '/^def /p' python_script.py
Example 18: System Administration Tasks
In daily administration, system administrators leverage sed for bulk user management, automated system configuration updates, and processing command output from other tools in complex pipelines.
Extract usernames from /etc/passwd:
sed 's/:.*$//' /etc/passwd
Find users with a specific shell:
sed -n '/\/bin\/bash$/p' /etc/passwd
Format disk usage output for easier reading:
df -h | sed '1d' | sed 's/\([0-9]\+\)%/[\1%]/'
Generate hosts file entries from a list:
sed 's/^/192.168.1./; s/$/.example.com/' server-list.txt
Example 19: Combining Sed with Other Commands
Ultimately, sed’s true power emerges when combined with other Unix tools in pipelines. These combinations let you build sophisticated text processing workflows that would require substantial code in traditional scripting languages.
Find and clean recent error logs with find -exec:
find ./logs -name "*.log" -mtime -1 -exec sed -n '/ERROR/p' {} + | sort -u
Process web server logs to extract IP addresses:
sed 's/^\([^ ]*\) .*/\1/' access.log | sort | uniq -c | sort -rn | head -10
The substitution stores the first space-delimited field, so both dotted IPv4 addresses and colon-separated IPv6 addresses remain intact before sorting and counting.
Clean up process list output:
ps aux | sed '1d' | sed 's/ \+/ /g' | cut -d' ' -f1,11
Extract and format package versions:
dpkg -l | sed -n '/^ii/p' | sed 's/ \+/ /g' | cut -d' ' -f2,3
Troubleshoot Common sed Command Errors
sed: can’t read file
If sed cannot open an input file, you usually have a typo in the path or you are running from the wrong directory. A missing file produces an error like this:
sed -n '/ERROR/p' app.log
sed: can't read app.log: No such file or directory
Check the path first, then run the command again with the corrected filename:
ls -l application.log
sed -n '/ERROR/p' application.log
Successful verification prints matching lines without a file error.
sed: unterminated s command
This happens when the substitution expression is missing a delimiter or closing quote. The broken form looks like this:
printf "color=blue\n" | sed 's/blue/green'
sed: -e expression #1, char 12: unterminated `s' command
Add the closing delimiter and verify with a small sample before running the expression on real files:
printf "color=blue\n" | sed 's/blue/green/'
color=green
sed: in-place edit permission denied
In-place edits fail when the current user cannot write to the target file or directory. A protected system file can produce an error like this:
sed -i 's/worker_processes auto;/worker_processes 2;/' /etc/nginx/nginx.conf
sed: couldn't open temporary file /etc/nginx/sedXXXXXX: Permission denied
Verify permissions, then rerun with elevated privileges if the file is system-owned:
ls -l /etc/nginx/nginx.conf
sudo sed -i.bak 's/worker_processes auto;/worker_processes 2;/' /etc/nginx/nginx.conf
Confirm the new value after editing:
grep '^worker_processes' /etc/nginx/nginx.conf
worker_processes 2;
Conclusion
Sed is ready for safe text processing when preview commands come before in-place edits, backups protect important files, and complex expressions move into reusable script files. Keep using disposable fixtures while learning, then apply the same patterns to logs, configuration files, and structured text once the output matches your intent.


Formatting tips for your comment
You can use basic HTML to format your comment. Useful tags currently allowed in published comments:
<code>command</code>command<strong>bold</strong><em>italic</em><blockquote>quote</blockquote>