Two Buffers, One Cycle
sed processes input one line at a time in a cycle: it reads a line into the pattern space, runs the script against it, and by default prints the pattern space at the end of the cycle. Alongside the pattern space sed keeps a second buffer called the hold space, which starts out containing a single empty line and persists across cycles. The hold space is sed's only long-term memory; without it, sed would be purely stateless, seeing each line in isolation. Commands that shuttle data between the two buffers unlock multi-line and stateful transformations.
Cricket analogy: The pattern space is the batsman currently on strike facing this ball; the hold space is the non-striker waiting at the other end, retaining context between deliveries until the two swap ends.
The Six Buffer Commands
Six single-letter commands move data between the buffers. Lowercase h copies the pattern space into the hold space (overwriting it), while uppercase H appends the pattern space to the hold space with an intervening newline. Lowercase g copies the hold space into the pattern space (overwriting it), and uppercase G appends the hold space to the pattern space with a newline. The x command exchanges the two buffers, swapping their contents. Note that this g is the hold-space get command, entirely distinct from the g flag of the substitute command.
Cricket analogy: h is like overwriting the scoreboard total with the current score; H is adding this over's runs to the accumulating tally; x is the two batsmen crossing to swap strike after a single.
# Reverse the order of all lines (emulate tac) using the hold space
sed -n '1!G;h;$p' file.txt
# 1!G -> for every line except the first, append hold space to pattern space
# h -> copy pattern space (line + accumulated tail) back to hold space
# $p -> on the last line, print the fully reversed accumulation
# Print each line together with the line before it (2-line window)
sed -n 'H;x;s/\n/ /;p' file.txtMulti-Line Idioms and State
Because the hold space survives between cycles, it lets sed accumulate lines and act on groups rather than singletons. The classic tac emulation sed -n '1!G;h;$p' builds up a reversed copy of the whole file in the hold space and prints it at the end. Other idioms use H to gather lines matching a pattern, then x and a substitute to join them. This statefulness is what elevates sed from a line filter to a small stream-processing language, though deeply nested hold-space scripts are notoriously hard to read and are often better expressed in awk or a scripting language.
Cricket analogy: Accumulating in the hold space is like a scorer building a full innings card ball by ball, then reading out the complete scorecard at the fall of the last wicket rather than commentating each ball in isolation.
The get command g and the substitute global flag g are completely different things: 'g' as a standalone command replaces the pattern space with the hold space, whereas the g at the end of s/x/y/g means replace all matches. Confusing the two is a common source of baffling sed bugs.
The hold space begins each run containing one empty line, not nothing. That is why H on the very first line often produces a leading blank line, and why idioms like 1!G guard against appending the empty hold space on the first cycle.
- sed keeps two buffers: the pattern space (current line) and the hold space (persistent memory).
- The hold space survives across cycles and starts as a single empty line.
- h/H copy/append the pattern space into the hold space.
- g/G copy/append the hold space into the pattern space.
- x exchanges the contents of the two buffers.
- The standalone g command is distinct from the substitute g flag.
- Hold-space idioms enable multi-line and stateful edits like reversing a file.
Practice what you learned
1. What does the hold space contain at the start of a sed run?
2. What does the uppercase H command do?
3. Which command exchanges the pattern space and the hold space?
4. How does the standalone g command differ from the g flag in s/foo/bar/g?
5. Why does the tac-emulating script sed -n '1!G;h;$p' use 1!G rather than plain G?
Was this page helpful?
You May Also Like
Substitute Command Flags
The flags that follow the sed substitute command control how many matches are replaced, whether matching is case-insensitive, and what happens after the replacement.
The Transform Command
The y command performs character-by-character transliteration, mapping each character in one set to the corresponding character in another, similar to the tr utility.
Reading and Writing Files
The r, R, w, and W commands let sed pull the contents of external files into the output stream and write matched lines out to separate files during a single pass.
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