Capturing Groups and Backreferences
Greedy quantifiers expand to match the last occurrence of a pattern; non-greedy quantifiers match the first occurrence.
The Stopping-Point Problem
A quantifier does more than decide how many characters a pattern may consume. It also influences where the match stops. With a greedy quantifier, the engine expands the match as far as it can and settles at the last valid stopping point. With a non-greedy quantifier, the engine stops at the first point where the rest of the pattern can be satisfied.
What do you think happens?
A pattern uses .+?@ on a string containing several @ symbols. Where will the match stop?
Reveal answer
At the first @ symbol
The question mark makes + non-greedy. The engine stops as soon as the rest of the pattern, here the @ symbol, can be satisfied.
Greedy Expansion and Backtracking
Think of a greedy quantifier as having a choice about where to stop. When .+ is applied to text containing multiple @ symbols, it initially matches as much as possible, continuing character by character toward the end of the string. The engine then checks whether the rest of the pattern is satisfied. If it is, the match settles at that last valid stopping point. If a later part of a pattern is not satisfied, the engine can backtrack and try an earlier stopping point.
The important point is that greedy does not simply mean “always use the longest text.” It means the quantifier first tries to extend the match. The final result is the last stopping point that allows the complete pattern to succeed.
The Non-Greedy Form
A non-greedy quantifier is made by appending a question mark to a quantifier. For example, .+ becomes .+?, and .* becomes .*?. The non-greedy form still performs the quantifier's basic repetition, but it stops as soon as the rest of the pattern can be satisfied.
| Pattern form | Stopping preference | Typical goal |
|---|---|---|
| .+ or .* | Expand toward the last valid stopping point | A later or larger match |
| .+? or .*? | Stop at the first valid stopping point | An earlier or individual match |
The choice depends on whether the task needs the first match or the last match.
Tracing a Repeated Delimiter
Finding the First @ in an Email List
Consider the pattern .+?@ applied to a string containing multiple @ symbols, including stephen.marquard@uct.ac.za.
- 1Start at the beginning
The pattern begins with .+?, so it must match one or more characters but does so non-greedily.
- 2Check the next delimiter
The engine reaches the first @ symbol in stephen.marquard@uct.ac.za and checks whether the rest of the pattern can be satisfied.
- 3Stop at the first valid point
Because the @ part is now satisfied, .+? stops instead of continuing toward a later @ symbol.
The pattern .+?@ matches from the beginning of the string through the first @ sign.
The same input can therefore produce a different substring when only the question mark changes. The greedy form .+@ tries to reach the last valid @, while the non-greedy form .+?@ pulls back to the earliest valid @.
Reading the Matching Path
To debug a pattern, trace two decisions: how far the quantifier first expands, and what happens when the remaining pattern is checked. A greedy quantifier first pushes outward. If the complete pattern cannot succeed at that position, matching backtracks to an earlier position. A non-greedy quantifier takes the opposite practical approach: it tests the earliest possible stopping point and expands only when the rest of the pattern is not yet satisfied.
Extraction Practice
You need to extract one item from text that contains several repeated delimiters. Decide whether to begin with a greedy quantifier or a non-greedy quantifier. Then explain what would make you change your choice after testing the match.
Hints
- Ask whether the task needs the first valid occurrence or the last valid occurrence.
- Remember that appending ? changes a quantifier from greedy to non-greedy.
- Trace where the quantifier first tries to stop and whether the rest of the pattern is satisfied there.
Mistakes to Avoid
Common mistake Assuming greedy matching always means the entire string will be returned.
What it looks likeA greedy quantifier expands, but the final match must still satisfy the complete pattern.
Why it failsThe quantifier settles at the last valid stopping point, not necessarily at the absolute end.
Do this insteadCheck what follows the quantifier and trace whether backtracking is required.
Common mistake Forgetting the question mark when the task needs the first occurrence.
What it looks likeUsing .+ instead of .+? when text contains several delimiters.
Why it failsThe greedy form tries to expand toward the last valid delimiter.
Do this insteadAppend ? to create the non-greedy form, such as .+? or .*?.
Common mistake Choosing greediness without identifying the extraction goal.
What it looks likeTreating greedy and non-greedy forms as interchangeable.
Why it failsThe two forms have different stopping preferences.
Do this insteadDecide first whether the task needs the first match or the last match.
Common mistake Debugging only the final substring instead of the matching path.
What it looks likeSeeing an unexpectedly long match but not considering expansion and backtracking.
Why it failsThe result becomes easier to explain when you track how far the quantifier expanded and where it tested the remaining pattern.
Do this insteadTrace expansion, the remainder check, and any return to an earlier stopping point.
Key Takeaways
- 1Greedy quantifiers expand toward the last valid stopping point.
- 2Non-greedy quantifiers stop at the first point where the rest of the pattern can be satisfied.
- 3Append ? to a quantifier to make it non-greedy, as in .+? and .*?.
- 4Backtracking means the engine can return to an earlier stopping point when the complete pattern is not satisfied.
- 5Choose greediness according to the extraction goal: first match or last match.
At a glance
- Greedy matching pushes outward and settles at the last valid stopping point.
- Non-greedy matching pulls back and settles at the first valid stopping point.
- Appending a question mark converts forms such as .+ and .* into .+? and .*?.
- Tracing expansion, remainder checks, and backtracking helps explain unexpected matches.
- For repeated delimiters, begin with a non-greedy form when the task calls for an individual or first item.