sed processes input line by line, applies your commands, and writes the result to standard output. The original file stays untouched unless you pass the -i flag. This makes it safe to preview any operation before committing it.
The general form of the delete command is:
bashsed 'ADDRESSd' file
ADDRESS selects which lines to delete. d is the delete command. Lines that do not match the address print as usual.
Delete a specific line by number:
bashsed '3d' file.txt # delete line 3sed '$d' file.txt # delete the last line
$ always refers to the last line regardless of file length, useful when you need to remove a trailing entry without counting lines first.
Delete multiple non-consecutive lines by separating addresses with a semicolon:
bashsed '2d;5d;8d' file.txt
Delete a block of consecutive lines with a range:
bashsed '3,6d' file.txt # delete lines 3 through 6sed '5,$d' file.txt # delete from line 5 to end of file
Adding ! after an address inverts the selection — it deletes everything that does NOT match. To keep only lines 3 through 5 and remove the rest:
bashsed '3,5!d' file.txt
This is a compact alternative to chaining head and tail to extract a slice.
GNU sed supports the first~step step address, which matches every Nth line starting at a given offset. To delete every even-numbered line:
bashsed '0~2d' file.txt
The offset 0 means the first match falls on line 2 (before the file starts, step of 2, so first match = line 2). To delete every third line starting from line 3:
bashsed '3~3d' file.txt
The first~step syntax is GNU sed only. It is not available in the BSD sed shipped with macOS.
Wrap a search pattern in slashes to delete matching lines:
bashsed '/error/d' file.txt
Pattern matching is a substring match — /bl/d would delete any line containing “bl”, including “black”. Be precise with your patterns.
To match case-insensitively, add the I flag after the closing slash:
bashsed '/Error/Id' file.txt
To invert the match and delete all lines that do NOT contain the pattern:
bashsed '/error/!d' file.txt
Use two patterns separated by a comma to delete a range between matching lines:
bashsed '/start/,/end/d' file.txt
sed starts deleting at the first line matching the opening pattern and stops after the first match of the closing pattern. Both endpoints are included in the deletion.
Mix a line number with a pattern when you know where the range starts but not where it ends:
bashsed '1,/header_end/d' file.txt
Remove truly empty lines with ^$ — the beginning anchor immediately followed by the end anchor:
bashsed '/^$/d' file.txt
This does not catch lines that contain only spaces or tabs. To remove those as well, use the POSIX [[:space:]] character class:
bashsed '/^[[:space:]]*$/d' file.txt
* matches zero or more whitespace characters, so this covers both empty lines and visually blank lines.
The pattern between slashes is a full regular expression:
bashsed '/^#/d' config.txt # strip comment lines starting with #sed '/;$/d' source.txt # remove lines ending with semicolonsed -E '/^.{0,4}$/d' file.txt # delete lines shorter than 5 characters
-E enables extended regular expressions — no need to escape { and }.
You can chain multiple commands in one expression. Commands execute left to right, and deleted lines never reach later ones:
bashsed '/^#/d; s/localhost/127.0.0.1/g' config.txt
This strips comment lines first, then applies the substitution only to remaining lines.
All the examples above write to standard output. To modify the file permanently, add -i:
bashsed -i '/^$/d' file.txt
Always preview without -i first. When ready, pass a suffix to save an automatic backup:
bashsed -i.bak '/^$/d' file.txt
This saves the original as file.txt.bak before modifying file.txt.
Never redirect output to the same input file — the shell truncates it before sed reads it:
bashsed '/^$/d' file.txt > file.txt # destroys the file
On macOS, BSD sed requires an explicit extension argument even when you do not want a backup file:
bashsed -i '' '/^$/d' file.txt
Use line numbers for exact positions, ! to invert selection, patterns for content-based deletion, and [[:space:]] for blank line cleanup. Always preview without -i first, and use -i.bak when editing in place. Leave a comment below if you run into any issues.