sed Address Negation with the ! Operator
Putting ! after a sed address runs the command on every line that does not match.
Sometimes it is easier to say which lines to skip. The ! operator flips any address so the command applies to the complement.
What it does
A ! immediately after an address negates it. The command then runs on all lines except those the address would have matched. It works with numbers, regexes, ranges, and the $ last-line address.
Common usage
sed '1!d' file # keep only line 1 (delete all others)
sed '/^#/!s/ /_/g' file # squeeze spaces except on comment lines
sed -n '/error/!p' app.log # print lines that do NOT match error
sed '$!N' file # join pairs, leaving last line aloneOptions
| Form | What it does |
|---|---|
| N!cmd | Run cmd on every line except line N |
| /regex/!cmd | Run cmd on lines not matching the regex |
| M,N!cmd | Run cmd outside the range M to N |
| $!cmd | Run cmd on every line except the last |
| addr !d | Delete everything except the addressed lines |
In CI
Negation is portable between GNU and BSD sed. A handy idiom is /pattern/!d to keep only matching lines, which behaves like grep but stays inside a single sed program when you are already running other commands.
Common errors in CI
Spacing matters: most builds accept both 1!d and 1 !d, but a stray ! with no address, such as a leading !d, raises sed: -e expression #1, char N: missing command or an unexpected `!' error. Keep the ! directly after the address.