sed text
find and replace without opening an editor. you're welcome.
The sed man page is 1,200 lines long. You need about five patterns and you can replace every “find and replace” dialog you’ve ever used.
You needed to change a string in a config file. So you opened it in nano. Or vim. Or VS Code. You pressed Ctrl+H. You typed the old string. You typed the new string. You clicked “Replace All.” You saved. You closed. One file done. Then you realized you need to change it in four more files. So you opened each one. Ctrl+H. Old string. New string. Replace All. Save. Close. Repeat. You just spent five minutes doing what one command does in half a second.
Or worse — you needed to change something across an entire codebase. So you opened VS Code, used the sidebar search, expanded “files to include,” typed a glob, waited for the workspace to index, clicked “Replace All” with a prayer, and then spent twenty minutes verifying it didn’t destroy something because you couldn’t see the changes before committing to them.
sed does all of this from the command line. On one file or a thousand. With a preview before you commit. Without opening anything.
Unless you’re running Windows then wtf none of this applies to you. But hey, come to the dark side, go install WSL2 and you can follow along. We’ll wait. Impatiently.
If you’re lazy like me (all sysadmins are!) then click here for the sed cheat sheet.
Find and replace (the thing you came here for)
sed 's/old/new/' file.txt
That’s it. Replaces the first occurrence of “old” with “new” on each line. Prints the result to your terminal. Does not modify the file — it just shows you what the output would look like. This is the preview.
Replace ALL occurrences on each line
sed 's/old/new/g' file.txt
The g at the end means “global” — every occurrence on every line, not just the first one. Without g, if a line has “old old old,” only the first one gets replaced.
Actually modify the file
sed -i 's/old/new/g' file.txt
-i means “in-place.” This edits the file directly. No preview. No undo button. Be sure before you use this. Or make a backup first:
sed -i.bak 's/old/new/g' file.txt
Creates file.txt.bak with the original, then modifies file.txt. Insurance.
Case-insensitive replace
sed 's/error/WARNING/gI' file.txt
The I flag (capital I) makes the match case-insensitive. Catches “Error,” “ERROR,” “error,” and everything in between.
Replace across multiple files
sed -i 's/old-api.example.com/new-api.example.com/g' *.conf
Every .conf file in the current directory. One command. No opening files. No clicking through tabs.
Recursively across a codebase
find . -name "*.py" -exec sed -i 's/old_function/new_function/g' {} +
Every Python file in the current directory tree. find locates the files, sed does the work. This replaces twenty minutes of IDE “search and replace across project.”
Delete lines
Delete lines matching a pattern
sed '/DEBUG/d' logfile.txt
Removes every line containing “DEBUG.” Prints the rest. Like grep -v but for when you want to clean up a file rather than filter output.
Delete a specific line number
sed '5d' file.txt
Deletes line 5. Because sometimes you know exactly which line needs to go.
Delete a range of lines
sed '10,20d' file.txt
Deletes lines 10 through 20. Useful for removing a block of configuration or a section of a log.
Delete blank lines
sed '/^$/d' file.txt
^$ matches empty lines (start of line immediately followed by end of line). Cleans up files with excessive whitespace. Your code reviewer will thank you.
Print specific lines
Print only matching lines
sed -n '/ERROR/p' file.txt
-n suppresses normal output. /ERROR/p prints only lines matching “ERROR.” This is essentially grep, but with sed’s other superpowers available in the same command.
Print a range of lines
sed -n '50,60p' file.txt
Lines 50 through 60. Like head and tail combined, but you pick the exact range.
Print the first line
sed -n '1p' file.txt
Just line 1. Sometimes that’s all you need.
Add text
Insert a line before a match
sed '/\[database\]/i # Database configuration follows' config.ini
Adds a comment line before any line matching [database]. The i command inserts before the match.
Append a line after a match
sed '/\[database\]/a host=localhost' config.ini
Adds host=localhost after the matching line. The a command appends after the match.
Use different delimiters
When your search or replace string contains /, the command gets ugly:
# Ugly — escaping slashes
sed 's/\/usr\/local\/bin/\/opt\/bin/g' file.txt
# Clean — use a different delimiter
sed 's|/usr/local/bin|/opt/bin|g' file.txt
You can use any character as the delimiter. |, #, @, whatever. Pick one that doesn’t appear in your strings.
Chain multiple operations
sed -e 's/foo/bar/g' -e 's/baz/qux/g' -e '/DEBUG/d' file.txt
Three operations in one pass: two replacements and a line deletion. Each -e adds another command. Faster than running sed three times.
The flags that actually matter
| Flag / Pattern | What it does |
|---|---|
s/old/new/ |
Substitute first match on each line. |
s/old/new/g |
Substitute all matches on each line. |
s/old/new/gI |
Substitute all, case-insensitive. |
-i |
Edit the file in-place (destructive). |
-i.bak |
In-place with backup (creates .bak file). |
-n |
Suppress default output (use with p). |
-e |
Add multiple commands in one invocation. |
/pattern/d |
Delete lines matching pattern. |
/pattern/p |
Print lines matching pattern (use with -n). |
/pattern/i text |
Insert text before matching lines. |
/pattern/a text |
Append text after matching lines. |
5d / 10,20d |
Delete by line number or range. |
“But I can just open it in—”
No.
“VS Code has find and replace.” VS Code has find and replace for one file at a time, unless you use the sidebar search, which requires indexing your workspace, loading the extension host, and hoping it doesn’t crash on a directory with 100,000 files. sed -i 's/old/new/g' *.py doesn’t need to load a UI.
“Sublime Text can search across files.” Sublime Text is $99 and also requires opening an application, loading a project, and clicking through dialogs. sed is free, pre-installed, and finishes before Sublime would have finished scanning.
“I use perl -pie for this.” Perl one-liners work. They’re also write-only code — nobody can read them six months later, including you. sed is more limited but more readable, and for 95% of find-and-replace tasks, it’s all you need.
“I’ll just use my IDE’s refactoring tools.” IDE refactoring is great for renaming variables and methods with semantic awareness. But you’re not always in an IDE. You’re SSH’d into a server at 2 AM changing a config value across twelve files. Your IDE is at home. sed is on every Linux box ever made.
sed cheat sheet
You made it. Or you skipped straight here. Either way, no judgment. Copy and paste these. Pin them. Tattoo them on your forearm. Whatever works.
| What you’re doing | Command |
|---|---|
| Replace (preview) | sed 's/old/new/g' file.txt |
| Replace (in-place) | sed -i 's/old/new/g' file.txt |
| Replace with backup | sed -i.bak 's/old/new/g' file.txt |
| Case-insensitive replace | sed 's/old/new/gI' file.txt |
| Replace in multiple files | sed -i 's/old/new/g' *.conf |
| Replace recursively | find . -name "*.py" -exec sed -i 's/old/new/g' {} + |
| Delete matching lines | sed '/pattern/d' file.txt |
| Delete blank lines | sed '/^$/d' file.txt |
| Delete line range | sed '10,20d' file.txt |
| Print matching lines | sed -n '/pattern/p' file.txt |
| Print line range | sed -n '50,60p' file.txt |
| Multiple operations | sed -e 's/a/b/g' -e 's/c/d/g' file.txt |
| Different delimiter | sed 's|/old/path|/new/path|g' file.txt |
The one command:
sed -i 's/old/new/g' file.txt— find and replace, in-place, done. Everything else is refinement.