The Auto-Print Model
sed processes input line by line into a buffer called the pattern space. By default, after running the script on each line, sed automatically prints the pattern space. This auto-print behaviour is why sed 's/a/b/' outputs every line, changed or not. The -n option suppresses auto-print, leaving you to emit lines explicitly with the p command. Understanding this model is essential: p and -n are two halves of the same idea, and misusing one without the other causes the classic 'everything printed twice' bug.
Cricket analogy: Auto-print is like the scoreboard updating after every ball whether or not a run is scored; -n turns off the automatic update so only the deliveries you explicitly signal get displayed.
The p Command
The p command prints the current pattern space immediately, at the point it appears in the script. Combined with -n, an address makes p a precise selector: sed -n '5p' prints only line 5, sed -n '/foo/p' prints matching lines (mimicking grep), and sed -n '1,10p' prints a range. Without -n, p duplicates lines because they get printed once by p and again by auto-print, which is occasionally useful for doubling lines but usually a mistake. The p flag on a substitution (s///p) prints only when the substitution actually succeeds.
Cricket analogy: sed -n '/foo/p' is a highlights package that shows only the boundaries; the p flag on a substitution is a replay triggered only when a wicket actually falls, not on every ball.
# grep-like: print only matching lines
sed -n '/ERROR/p' log.txt
# Print a specific line and a range
sed -n '5p' file.txt
sed -n '10,20p' file.txt
# Print only lines where the substitution succeeded
sed -n 's/^user=//p' accounts.txt
# Delete blank lines
sed '/^$/d' file.txt
# Delete a range of lines and keep the rest
sed '5,10d' file.txt
# D vs d in a multiline gap-squeezing script
sed '/^$/{ N; /^\n$/D }' file.txt # collapse runs of blank lines to oneThe d Command and Its Sibling D
The d command deletes the entire pattern space and starts the next cycle immediately, so no auto-print happens and any commands after d on that line are skipped. It is the workhorse for filtering: /^$/d removes blank lines, /^#/d strips comments, and 5,10d drops a block. The uppercase D behaves differently and only matters when the pattern space holds multiple lines (built up with N): D deletes text up to and including the first embedded newline, then restarts the cycle WITHOUT reading new input, re-running the script on the remainder. This makes D the key to loops that squeeze repeated blank lines.
Cricket analogy: The d command is a clean-bowled dismissal that ends the batter's innings instantly, skipping everything after; D is a run-out of only the striker, leaving the non-striker to face the next ball without a fresh over starting.
sed -n 's/pattern/&/p' is a common trick to print only lines containing a pattern while leaving them unchanged, since & re-inserts the match. It is equivalent to grep but stays within a single sed invocation.
Any command placed after d on the same line will never run, because d immediately ends the current cycle. If you write '/x/d; s/a/b/', the substitution is skipped on lines matching /x/. Order commands so cleanup happens before deletion.
Choosing Between p, d, and -n
For extracting a subset of lines, prefer sed -n with p: it is explicit and avoids duplicates. For removing a subset while passing everything else through unchanged, prefer d without -n so auto-print handles the survivors. The two approaches are complementary inverses: sed -n '/foo/p' and sed '/foo/!d' both keep only foo lines, while sed '/foo/d' and sed -n '/foo/!p' both remove them. Choosing the idiom that reads most directly for your intent makes scripts easier to maintain and less prone to the double-print trap.
Cricket analogy: Choosing p versus d is picking your dismissal method for the situation: p is nominating exactly which batters to show on the highlights, d is declaring which to send back, and both can achieve the same final scorecard.
- sed auto-prints the pattern space after each cycle unless -n is given.
- The p command prints the pattern space immediately; with -n it becomes a precise line selector.
- Using p without -n duplicates lines because both p and auto-print emit them.
- The s///p flag prints only when the substitution actually succeeds.
- d deletes the pattern space and starts the next cycle, skipping any later commands on that line.
- D deletes up to the first embedded newline and restarts the script on the remainder without reading new input, key to multi-line loops.
- For extraction use sed -n with p; for filtering use d with auto-print; the idioms are complementary inverses.
Practice what you learned
1. Why does 'sed "5p"' print line 5 twice?
2. What does the -n option do?
3. What happens to commands placed after d on the same matching line?
4. How does D differ from d?
5. What does sed -n 's/^user=//p' do?
Was this page helpful?
You May Also Like
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.
Line Ranges and Steps
Selecting spans of lines in sed using numeric ranges, the $ last-line symbol, regex-bounded ranges, and GNU's first~step notation for periodic selection.
Regular Expressions in sed
How sed matches text using Basic and Extended Regular Expressions, including anchors, character classes, quantifiers, and the escaping rules that trip people up.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics