/commands/sed/sed-delete-lines-matching-pattern
sed '/pattern/d': delete lines matching a pattern
- tool
- sed
- versions
- GNU sed 4.x
- os
- linux, macos, windows
sed '/pattern/d' file prints the file without the lines that match pattern; sed -i '/pattern/d' file edits the file in place. The d command deletes the pattern space, and the /regex/ before it is the address that selects which lines it applies to. Add ! ('/pattern/!d') to keep only the matching lines instead.
Examples
printf 'keep 1\n# comment\nkeep 2\n\nDEBUG noise\nkeep 3\n' > app.conf
echo '--- drop comments:'; sed '/^#/d' app.conf
echo '--- drop comments and empty lines:'; sed -e '/^#/d' -e '/^$/d' app.conf
echo '--- keep only lines with keep:'; sed '/keep/!d' app.conf
echo '--- case-insensitive (GNU):'; sed '/debug/Id' app.confOutput
--- drop comments: keep 1 keep 2 DEBUG noise keep 3 --- drop comments and empty lines: keep 1 keep 2 DEBUG noise keep 3 --- keep only lines with keep: keep 1 keep 2 keep 3 --- case-insensitive (GNU): keep 1 # comment keep 2 keep 3
Edit the file in place
printf 'a\nTODO remove me\nb\n' > notes.txt
sed -i.bak '/TODO/d' notes.txt
cat notes.txt
ls notes.txt*Output
a b notes.txt notes.txt.bak
-i.bak keeps a backup copy. On macOS (BSD sed) -i needs an argument, so write sed -i '' '/TODO/d' notes.txt there, or -i.bak, which works on both.
Other addresses
| Command | Deletes |
|---|---|
| sed '3d' | Line 3 |
| sed '2,4d' | Lines 2 to 4 |
| sed '$d' | The last line |
| sed '/start/,/end/d' | From a line matching start to the next line matching end |
| sed '/^[[:space:]]*$/d' | Empty lines and lines with only whitespace |
| sed '/^#/d;/^$/d' | Comments and empty lines (two commands separated by ;) |
Delete around a match
The n command prints the current line and reads the next one, so '/start/{n;d}' keeps the matching line and deletes the one after it. A range ending in $ deletes from the first match to the end of the file.
printf 'header\nstart\nskip me\nlast\n' > f.txt
echo '--- delete the line after start:'; sed '/start/{n;d}' f.txt
echo '--- delete from start to the end:'; sed '/start/,$d' f.txt
echo '--- delete lines matching foo or bar (GNU -E):'; printf 'foo\nok\nbar\n' | sed -E '/foo|bar/d'Output
--- delete the line after start: header start last --- delete from start to the end: header --- delete lines matching foo or bar (GNU -E): ok
Common errors
- A
/inside the pattern ends the address early.sed '/usr/local/d'fails withsed: -e expression #1, char 7: extra characters after command; escape the slashes ('/\/usr\/local/d') or use another delimiter as shown below. sed: -e expression #1, char N: unterminated address regexmeans the closing delimiter is missing, often because a quote ended the script too early.- On macOS,
sed -i '/x/d' filewithout a backup suffix fails because BSD sed takes the next argument as the suffix; see GNU vs BSD sed. - The
Iflag for case-insensitive matching is GNU only. With BSD sed use a bracket expression such as/[Dd][Ee][Bb][Uu][Gg]/d.
Which tool to use
For read-only filtering, grep -v 'pattern' file gives the same output as sed '/pattern/d' file and is easier to read. Use sed when you need to edit the file in place, combine deletion with substitutions in one pass, or delete ranges of lines. In Vim, the same job is :g/pattern/d (see vim: delete lines matching a pattern).
FAQ
How do I preview what sed '/pattern/d' will delete?
Print the matching lines first with sed -n '/pattern/p' file or count them with grep -c 'pattern' file. Run sed -i only after the preview shows the lines you expect.
How do I delete lines that match either of two patterns?
Give two commands, sed -e '/foo/d' -e '/bar/d' file, or use an extended regex alternation with GNU sed, sed -E '/foo|bar/d' file.
Does sed -i really edit the file in place?
GNU sed writes the result to a temporary file and renames it over the original, so the file gets a new inode and hard links to the old file keep the old content.