sed is useful when a shell pipeline needs to change text or keep only particular lines. Its safest default is also easy to overlook: it prints transformed output to the terminal and leaves the input file alone. That makes it practical to preview an edit before deciding whether to change the original.
Think in terms of input, address, and command
sed reads input one line at a time. An expression can include an optional address that chooses which lines to act on, followed by a command that says what to do:
sed 'address command' file
For example, this changes the first old on each line of the output:
printf '%s\n' 'host=old.example' | sed 's/old/new/'
The result is host=new.example. The input file is untouched; here, the input is a pipeline rather than a file.
Quotes keep the expression together as one argument. Single quotes are a useful default for fixed expressions because they prevent the shell from expanding special characters such as $ before sed receives them.
Replace text with s
The substitution command has this shape:
s/pattern/replacement/flags
By default, it replaces only the first match on each line. Add g to replace every match on each line:
printf '%s\n' 'red red red' | sed 's/red/blue/'
printf '%s\n' 'red red red' | sed 's/red/blue/g'
The first output line is blue red red; the second is blue blue blue.
A pattern can be a regular expression, not just literal text. In a regular expression, . matches any single character. If your pattern or replacement contains /, you can choose another delimiter to make the expression easier to read:
printf '%s\n' '/srv/old/site' | sed 's#/srv/old#/srv/new#'
This prints /srv/new/site. If the delimiter you chose appears inside the pattern or replacement, escape it with a backslash. In replacement text, & stands for the complete match; write \& when you want a literal ampersand.
You can also limit a substitution to a particular line. This changes only the first draft on line 2:
sed '2s/draft/published/' notes.txt
Select or remove lines
Sed prints every input line by default. Use -n to suppress that output, then p to print only lines that match an address:
sed -n '2p' file.txt
sed -n '/error/p' application.log
The first command prints line 2. The second prints lines containing error. If you only need to find matching lines, grep is often the simpler choice; this guide to searching with grep covers that side of the job.
The d command removes addressed lines from the output. It does not delete them from the input file unless you also request in-place editing:
printf '%s\n' keep skip keep | sed '/skip/d'
The output contains two lines: keep and keep.
Addresses can be line numbers or ranges. For example, these print lines 2 through 4, or omit them from the output:
sed -n '2,4p' file.txt
sed '2,4d' file.txt
A range can also start and end at patterns. This prints the lines from a BEGIN match through an END match, including the boundary lines:
sed -n '/BEGIN/,/END/p' file.txt
Combine small edits in a pipeline
You can run multiple commands in one expression, separated by semicolons. This example changes every draft on a line, then removes blank lines:
sed 's/draft/final/g; /^$/d' report.txt
Sed is a good fit for compact, line-based transformations. If your task needs field-aware processing or calculations, awk may be easier to follow. When you want to display command output and save it at the same time, tee can pass output along while writing a file.
Preview before editing a file
Run the command without -i first. For example, preview a replacement in a configuration file:
sed 's/old.example/new.example/g' app.conf
Inspect the output before applying the change. In-place editing can overwrite a configuration file, so make a recoverable copy and verify the result before using it in a production environment.
The syntax for -i differs between common sed implementations. With GNU sed, this form edits the file and creates a backup named app.conf.bak:
sed -i.bak 's/old.example/new.example/g' app.conf
BSD/macOS sed uses a separate suffix argument when creating a backup:
sed -i '.bak' 's/old.example/new.example/g' app.conf
Its no-backup form is:
sed -i '' 's/old.example/new.example/g' app.conf
That last command edits the original without creating a backup. If you use it, keep a separate copy first. When a script needs to run on multiple platforms, check the target system's man sed and test the command on sample input; GNU-specific features and in-place syntax are not universal.
I originally published a more detailed version of this guide on the SSHFlow blog.
I'm also building SSHFlow — an SSH client where every server gets its own workspace for terminals, SFTP, code, and databases.
Top comments (0)