100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Programming

Negating Addresses

Using the ! operator to invert a sed address so a command runs on every line the address does NOT select, plus common idioms and gotchas.

Patterns & AddressingIntermediate8 min readJul 10, 2026
Analogies

Inverting a Match with !

Placing an exclamation mark immediately after an address negates it, so the command runs on every line the address does NOT match. If /foo/d deletes lines containing foo, then /foo/!d deletes every line that lacks foo, effectively keeping only the foo lines. The ! sits between the address and the command letter, and it works with single addresses, ranges, and step addresses alike. This inversion is one of sed's most compact tools for expressing 'everything except'.

🏏

Cricket analogy: Negation is a reverse sweep in selection: /foo/!d keeps only the foo lines the way a captain fields everyone except the non-strikers, dismissing all who don't fit the plan.

Negating Ranges and Steps

Negation composes with any address form. A negated numeric range like 2,4!d deletes every line outside lines 2 through 4, keeping only that middle block. A negated last-line address $!d deletes all lines except the last, a compact way to print just the final line's content after deletion. Because the ! attaches to the whole address, /A/,/B/!s/x/y/ substitutes on every line that falls outside the A-to-B region. Negation therefore turns any selection into its exact complement without rewriting the pattern.

🏏

Cricket analogy: Negating a range 2,4!d is like protecting the middle order and dismissing everyone else; only overs 2 to 4 survive while the rest of the innings is scrubbed.

bash
# Keep only lines containing 'ERROR' (delete everything else)
sed '/ERROR/!d' log.txt

# Substitute on every line EXCEPT those inside a code block
sed '/```/,/```/!s/foo/bar/g' notes.md

# Print only the last line: delete all but the last, print what remains
sed -n '$!d; p' file.txt      # or simply: sed -n '$p'

# Comment out every line that is NOT already a comment
sed '/^#/!s/^/# /' config.txt

# Delete every line outside lines 5-10
sed '5,10!d' file.txt

The idiom /pattern/!d is functionally the grep of sed: it discards non-matching lines, leaving a stream equivalent to grep 'pattern'. It is handy inside larger sed scripts where spawning grep would be awkward.

Placement and Common Mistakes

The ! must come after the address and before the command, with the address itself unaltered. Writing !/foo/d is a syntax error; the correct form is /foo/!d. GNU sed tolerates whitespace and even multiple exclamation marks (an even count cancels out), but POSIX only guarantees a single ! directly after the address. When combining with block braces, the ! applies to the whole group: /A/,/B/!{ s/x/y/; s/p/q/; } runs both substitutions on lines outside the range. Misplacing the ! inside the braces would negate only the first command.

🏏

Cricket analogy: Placing ! correctly is like appealing at the right moment: /foo/!d works, but !/foo/d is appealing before the ball is bowled, and the umpire rejects it outright.

When negation is paired with braces, position matters: /A/,/B/!{ cmd1; cmd2; } negates the whole block, but /A/,/B/{ cmd1!; cmd2; } negates only cmd1. Decide whether you want to invert the address or a single inner command.

  • A trailing ! after an address negates it, running the command on non-matching lines.
  • /pattern/!d keeps only matching lines, acting like grep inside sed.
  • Negation works with single addresses, numeric ranges, $, and step addresses.
  • $!d deletes everything but the last line; 2,4!d keeps only lines 2 through 4.
  • The ! must sit between the address and the command; !/foo/d is a syntax error.
  • With braces, /A/,/B/!{ ... } negates the entire block, not just one inner command.

Practice what you learned

Was this page helpful?

Topics covered

#Programming#SedStreamEditorStudyNotes#NegatingAddresses#Negating#Addresses#Inverting#Match#StudyNotes#SkillVeris#ExamPrep