The sed command in Linux is a stream editor that transforms text from files or pipelines without opening an editor. Unlike traditional editors that load entire files into memory and require interactive input, sed processes text line by line, applying commands you specify and outputting the result instantly. This design makes it perfect for automated text processing in scripts, data pipelines, and one-off command-line tasks where speed and precision matter.
This guide covers everything from installing GNU sed on minimal images to understanding the pattern and hold space buffers, applying address ranges, scripting with loops and branching, and chaining sed with other Unix tools for real-world automation. Follow along to practice selective printing, deletions, insertions, file reads and writes, multi-line operations, and reusable sed scripts that handle logs, CSV data, configuration files, and deployment workflows.
Why the sed Command Matters
Sed slips into everyday workflows because it reads from pipelines, respects automation, and works reliably across distributions without extra tooling. It also delivers far more than basic substitutions, handling selective printing, line insertion, multi-line transformations, and file I/O in the same lightweight binary.
- System administrators extract targeted log entries, filter configuration snippets, renumber documentation, and automate bulk edits across sprawling directories.
- Developers wire sed into build pipelines to inject version strings, strip comments before deployment, or reshape configuration templates during packaging.
- Data analysts chain sed with other CLI tools to clean CSV exports, normalize delimiters, and isolate fields without reaching for heavier scripting languages.
If you specifically need in-depth coverage of finding and replacing strings in files, including handling special characters, working with delimiters, and troubleshooting cross-platform differences, see our dedicated sed find and replace guide. This article focuses on the broader sed command capabilities: printing specific lines, deleting patterns, inserting and appending text, working with address ranges, multi-line operations, hold space and pattern space manipulation, reading and writing files, and building reusable sed scripts for complex automation tasks.
Understand the sed Command
If you are new to sed, think of it as a command-line text processor that reads input line by line, applies transformation rules you specify, and outputs the result. Unlike opening a file in an editor, sed processes streams of text, making it perfect for pipelines where data flows from one command to another without creating temporary files.
Basic Syntax
Specifically, the basic syntax follows this pattern:
sed [OPTIONS] 'COMMAND' [INPUT-FILE]
Breaking down each component:
- OPTIONS: Flags that modify sed’s behavior, such as
-ifor in-place editing,-nfor suppressing automatic output, or-Efor extended regular expressions. These are optional and can be combined (e.g.,-n -i.bak). - 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, sed reads from standard input (stdin), allowing you to pipe data from other commands like
cat file.txt | sed 's/foo/bar/'orcurl https://example.com | sed '/ads/d'.
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.
Workflow Cycle
In general, the typical sed workflow follows this cycle:
- 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.
In addition, here are the most useful options and commands organized by task:
Sed Command Reference Table
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 |
Consequently, the “suppresses automatic output” behavior of -n means sed won’t print every line by default. Normally, sed prints all input lines (whether changed or not), but -n turns off this behavior so you control exactly what gets printed using the p command. This is essential when you want to extract specific lines instead of transforming the entire file.
Install sed on Popular Linux Distributions
GNU sed ships with virtually every mainstream Linux distribution, but minimal containers or stripped-down images may omit it. Verify availability first, then install the package that adds the full-featured GNU sed binary if it is missing.
Check whether sed is already present:
sed --version
If the command is not found, use 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
The package name is sed across these distributions, so the commands above install the GNU implementation that supports the features used throughout this guide.
Basic Examples of Sed Command in Linux
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
For comprehensive coverage of find-and-replace operations including global substitution, case-insensitive matching, handling special characters, delimiter choices, and in-place editing with backups, see our dedicated sed find and replace guide which covers substitution operations in depth.
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 file:
sed -n '5p' /var/log/syslog
Next, pull lines 10 through 20:
sed -n '10,20p' /etc/services
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 Usage of the Sed Command in Linux
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
sed '/^$/{N;/^\n$/d;}' file-with-blank-lines.txt
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:
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 Real-World Examples
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 '/ERROR\|WARN/p' application.log
Next, remove debug and trace messages:
sed '/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:
echo "Name,Age,City\nJohn,30,NYC\nJane,25,LA" | 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.
Change a configuration value:
sed -i 's/^max_connections = .*/max_connections = 200/' postgresql.conf
Enable a commented-out setting:
sed -i 's/^# *\(listen_addresses\)/\1/' postgresql.conf
Update multiple related settings in one pass:
sed -i -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 -i '/^\[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:
VERSION="2.4.1"
sed -i "s/VERSION_PLACEHOLDER/$VERSION/" version.h
Convert Markdown headers to HTML:
sed -E 's/^## (.*)$/\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 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:
cat server-list.txt | sed 's/^/192.168.1./' | sed 's/$/.example.com/'
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:
find /var/log -name "*.log" -mtime -1 -exec sed -n '/ERROR/p' {} + | sort | uniq
Process web server logs to extract IP addresses:
cat access.log | sed 's/^\([^ ]*\) .*/\1/' | 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
Conclusion
Overall, the sed command provides fast, scriptable text transformations for virtually any text processing task in Linux. By understanding pattern space and hold space buffers, mastering address ranges and multi-line operations, using read and write commands for file manipulation, leveraging sed script files for complex reusable workflows, and knowing how to chain sed with other Unix tools in pipelines, you can confidently automate text processing tasks that range from simple line deletions to complex multi-file transformations. For in-depth coverage of text substitution operations, see our companion guide on finding and replacing strings with sed.