sed — Stream Editor for Text Transformation

Filter and transform text with sed — substitution, in-place editing, line addressing, deletion and back-references for scripts and pipelines.

sed (stream editor) reads text line by line and applies editing commands as the data flows through – no interactive editor, no temp files. Its bread and butter is search-and-replace with s/pattern/replacement/, but it also deletes, inserts, prints and reorders lines, addressed by number or by regex. You will reach for it whenever you need to patch config files, rewrite URLs, strip whitespace or massage command output in a pipeline. This guide walks from basic substitution through in-place editing, line addressing and back-references to the recipes you actually use.

Basic Substitution

sed 's/<pattern>/<replacement>/' <file> — Replace the first occurrence of pattern on each line.

sed 's/foo/bar/' input.txt

sed 's/<pattern>/<replacement>/g' <file> — Replace all occurrences of pattern on each line (global).

sed 's/foo/bar/g' input.txt

sed 's/<pattern>/<replacement>/gi' <file> — Replace all occurrences, case-insensitive.

sed 's/error/warning/gi' log.txt

sed 's/<pattern>/<replacement>/2' <file> — Replace only the Nth occurrence of pattern on each line.

sed 's/the/THE/2' input.txt

sed 's/<pattern>/<replacement>/gp' <file> — Replace globally and print only the changed lines (use with -n).

sed -n 's/error/ERROR/gp' log.txt

In-Place Editing

sed -i 's/<pattern>/<replacement>/g' <file> — Edit the file in-place (modifies the original file directly).

sed -i 's/localhost/production.example.com/g' config.yml

sed -i.bak 's/<pattern>/<replacement>/g' <file> — Edit in-place and create a backup with the given suffix.

sed -i.bak 's/debug=true/debug=false/g' config.ini

sed -i '' 's/<pattern>/<replacement>/g' <file> — Edit in-place without backup (macOS/BSD syntax, empty suffix required).

sed -i '' 's/old/new/g' config.yml

sed -i 's/<pattern>/<replacement>/g' <file1> <file2> — Edit multiple files in-place with the same substitution.

sed -i 's/v1.0/v2.0/g' README.md CHANGELOG.md

Delimiters & Special Characters

sed 's|<pattern>|<replacement>|g' <file> — Use | as delimiter instead of /. Useful when patterns contain slashes.

sed 's|/usr/local|/opt|g' paths.conf

sed 's#<pattern>#<replacement>#g' <file> — Use # as delimiter. Any character can serve as delimiter.

sed 's#http://#https://#g' urls.txt

sed 's/[[:space:]]*$//' <file> — Remove trailing whitespace from each line.

sed 's/[[:space:]]*$//' source.py

sed 's/^[[:space:]]*//' <file> — Remove leading whitespace from each line.

sed 's/^[[:space:]]*//' messy.txt

sed 's/&/\&amp;/g; s/</\&lt;/g; s/>/\&gt;/g' <file> — Escape HTML special characters.

sed 's/&/\&amp;/g; s/</\&lt;/g; s/>/\&gt;/g' input.html

Address Selection (Line Targeting)

sed '<n>s/<pattern>/<replacement>/' <file> — Substitute only on a specific line number.

sed '3s/old/new/' config.txt

sed '<n>,<m>s/<pattern>/<replacement>/g' <file> — Substitute on a range of lines (from line n to line m).

sed '10,20s/foo/bar/g' data.txt

sed '$s/<pattern>/<replacement>/' <file> — Substitute only on the last line. $ addresses the last line.

sed '$s/$/;/' data.csv

sed '/<regex>/s/<pattern>/<replacement>/g' <file> — Substitute only on lines matching a regex pattern.

sed '/^#/s/TODO/DONE/g' script.sh

sed '/<start>/,/<end>/s/<pattern>/<replacement>/g' <file> — Substitute within a range defined by two regex patterns.

sed '/<body>/,/<\/body>/s/class="old"/class="new"/g' page.html

sed '1,/<pattern>/s/<old>/<new>/g' <file> — Substitute from the first line until a pattern is matched.

sed '1,/---/s/draft/published/g' post.md

sed '0~2s/<pattern>/<replacement>/g' <file> — Substitute on every 2nd line (GNU sed step address: start~step).

sed '0~2s/^/>> /' data.txt

Deleting Lines

sed '<n>d' <file> — Delete a specific line by number.

sed '5d' data.txt

sed '<n>,<m>d' <file> — Delete a range of lines.

sed '3,7d' data.txt

sed '$d' <file> — Delete the last line of the file.

sed '$d' data.txt

sed '/<pattern>/d' <file> — Delete all lines matching a pattern.

sed '/^#/d' config.ini

sed '/^$/d' <file> — Delete all empty lines.

sed '/^$/d' messy.txt

sed '/^[[:space:]]*$/d' <file> — Delete all blank lines (empty or whitespace-only).

sed '/^[[:space:]]*$/d' messy.txt

sed '/<start>/,/<end>/d' <file> — Delete all lines between two patterns (inclusive).

sed '/BEGIN_GENERATED/,/END_GENERATED/d' output.txt

sed '/<pattern>/!d' <file> — Delete all lines NOT matching a pattern (inverse, like grep).

sed '/ERROR/!d' log.txt

Inserting & Appending

sed '<n>i\<text>' <file> — Insert text before a specific line.

sed '1i\# Configuration File' config.ini

sed '<n>a\<text>' <file> — Append text after a specific line.

sed '5a\# New section starts here' config.ini

sed '/<pattern>/i\<text>' <file> — Insert text before lines matching a pattern.

sed '/\[database\]/i\# Database settings' config.ini

sed '/<pattern>/a\<text>' <file> — Append text after lines matching a pattern.

sed '/^server {/a\    listen 443 ssl;' nginx.conf

sed '<n>c\<text>' <file> — Replace (change) an entire line with new text.

sed '3c\new_value = true' config.ini

sed '/<pattern>/c\<text>' <file> — Replace entire lines matching a pattern with new text.

sed '/^debug=/c\debug=false' config.ini

Back-References & Groups

sed 's/\(<pattern>\)/\1<suffix>/g' <file> — Capture a group with ( ) and reference it with \1 in the replacement.

sed 's/\(version\)=.*/\1=2.0/' config.ini

sed -E 's/(<pattern>)/\1<suffix>/g' <file> — Extended regex mode. Use ( ) for groups instead of ( ).

sed -E 's/(version)=.*/\1=2.0/' config.ini

sed -E 's/(<p1>)(<p2>)/\2\1/g' <file> — Swap two captured groups using back-references.

sed -E 's/([a-z]+), ([a-z]+)/\2 \1/g' names.txt

sed 's/.*/(&)/' <file> — The & in replacement refers to the entire matched text.

sed 's/.*/(&)/' list.txt

sed -E 's/([0-9]{4})-([0-9]{2})-([0-9]{2})/\3.\2.\1/g' <file> — Reformat dates from YYYY-MM-DD to DD.MM.YYYY using three groups.

sed -E 's/([0-9]{4})-([0-9]{2})-([0-9]{2})/\3.\2.\1/g' dates.txt

Printing & Output Control

sed -n '<n>p' <file> — Print only a specific line. -n suppresses default output.

sed -n '10p' data.txt

sed -n '<n>,<m>p' <file> — Print a range of lines.

sed -n '5,15p' data.txt

sed -n '/<pattern>/p' <file> — Print only lines matching a pattern (like grep).

sed -n '/ERROR/p' log.txt

sed -n '/<start>/,/<end>/p' <file> — Print lines between two patterns (inclusive).

sed -n '/BEGIN/,/END/p' config.txt

sed -n '$=' <file> — Print the total number of lines in the file (like wc -l).

sed -n '$=' data.txt

sed '/<pattern>/q' <file> — Quit after printing the first line matching a pattern.

sed '/^END$/q' stream.txt

Multiple Commands

sed -e 's/<p1>/<r1>/g' -e 's/<p2>/<r2>/g' <file> — Apply multiple substitution commands with -e flags.

sed -e 's/foo/bar/g' -e 's/baz/qux/g' input.txt

sed 's/<p1>/<r1>/g; s/<p2>/<r2>/g' <file> — Chain multiple commands with semicolons.

sed 's/http/https/g; s/www\.//g' urls.txt

sed -f <script_file> <file> — Read sed commands from a script file (one command per line).

sed -f transforms.sed input.txt

sed '{ s/<p1>/<r1>/g; s/<p2>/<r2>/g; }' <file> — Group multiple commands with curly braces.

sed '/^title/{ s/old/new/g; s/draft/final/g; }' document.md

Transliteration

sed 'y/<source_chars>/<dest_chars>/' <file> — Transliterate characters (like tr). Maps each character one-to-one.

sed 'y/abc/ABC/' input.txt

sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/' <file> — Convert all uppercase letters to lowercase.

sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/' input.txt

Common Recipes

sed -E 's/^[[:space:]]+|[[:space:]]+$//g' <file> — Trim leading and trailing whitespace from each line.

sed -E 's/^[[:space:]]+|[[:space:]]+$//g' messy.txt

sed '/^$/N;/^\n$/d' <file> — Squeeze multiple consecutive blank lines into one.

sed '/^$/N;/^\n$/d' messy.txt

sed 's/^/ /' <file> — Indent every line by 4 spaces.

sed 's/^/    /' code.py

sed '=' <file> | sed 'N;s/\n/\t/' — Add line numbers followed by a tab to each line.

sed '=' script.sh | sed 'N;s/\n/\t/'

sed -E 's/([^ ]+)/"\1"/g' <file> — Wrap each word in double quotes.

sed -E 's/([^ ]+)/"\1"/g' words.txt

sed -E 's/,.*//' <file> — Extract the first field from a CSV (everything before the first comma).

sed -E 's/,.*//' data.csv

sed -e :a -e '/\\$/N; s/\\\n//; ta' <file> — Join lines ending with a backslash (line continuation).

sed -e :a -e '/\\$/N; s/\\\n//; ta' Makefile

Pipelines

<command> | sed 's/<pattern>/<replacement>/g' — Use sed as a filter in a pipeline to transform output.

cat /etc/passwd | sed 's/:.*//'

<command> | sed -n '/<pattern>/p' — Filter output to show only matching lines.

env | sed -n '/^PATH/p'

<command> | sed '1d' — Remove the first line (header) from command output.

docker ps | sed '1d'

<command> | sed 's/\x1b\[[0-9;]*m//g' — Strip ANSI color codes from command output.

ls --color=always | sed 's/\x1b\[[0-9;]*m//g'

Conclusion

sed turns repetitive text edits into one-liners you can drop into scripts and pipelines. For everyday work, s///g, line deletion with d and selective printing with -n …p cover most cases. The one flag to treat with respect is -i: it overwrites the original file with no undo, so get into the habit of writing -i.bak to keep a backup – or run the command without -i first and eyeball the output. Be aware of GNU/BSD differences: GNU sed takes -i with no argument, whereas BSD/macOS sed requires sed -i ''; step addresses like 0~2 and \x1b escapes are GNU extensions too.

Further Reading

  • awk – field-aware text processing for column data and reports
  • grep – find the lines first, then transform them with sed
  • tr – fast character-level translation and deletion