Concepts / Capturing Groups and Backreferences

Capturing Groups and Backreferences

Greedy quantifiers expand to match the last occurrence of a pattern; non-greedy quantifiers match the first occurrence.

  • Programming

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?

  • At the first @ symbol
  • At the last @ symbol
  • It will always consume the entire string
Reveal answer

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.

beginkeep expandingcheckyesnotry againStartExpandconsume more charactersEnd of stringTest patternis the rest satisfied?Backtracktry an earlier stopValid matchlast valid stopping point
How does a greedy quantifier expand, test the remaining pattern, and settle on a valid 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.

formsformsappend.pattern element.pattern element+one or more+one or more?stop earlier
What changes in the pattern when a question mark is appended to a quantifier?
Pattern formStopping preferenceTypical goal
.+ or .*Expand toward the last valid stopping pointA later or larger match
.+? or .*?Stop at the first valid stopping pointAn earlier or individual 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.

Start at the beginning: The pattern begins with .+?, so it must match one or more characters but does so non-greedily.

Check 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.

Stop 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.

matches throughmatches through.+@expand first.+?@stop earlylast @last valid stopfirst @first valid stop
What different stopping behavior results from using .+@ versus .+?@ on text containing multiple @ symbols?

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.

starttestyesnoretryBegin matchConsume charactersgreedy expansionCheck remaindercomplete pattern?Match succeedsEarlier positionbacktrack
What matching path does the engine follow when a long match fails later and must backtrack?
storesreuseschecksInput textCapturing groupcaptured textBackreferencesame captured textPattern match
What text is stored by a capturing group, and how can a later backreference reuse that exact captured text?

Extraction Practice

MEDIUM

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.
selectsselectsGreedy pattern.+Non-greedy pattern.+?Later boundarylast valid stopEarlier boundaryfirst valid stop
When extracting content between repeated delimiters, how does the selected quantifier change the returned portion?

Mistakes to Avoid

  • Assuming greedy matching always means the entire string will be returned.

    The quantifier settles at the last valid stopping point, not necessarily at the absolute end.

    Fix: Check what follows the quantifier and trace whether backtracking is required.

  • Forgetting the question mark when the task needs the first occurrence.

    The greedy form tries to expand toward the last valid delimiter.

    Fix: Append ? to create the non-greedy form, such as .+? or .*?.

  • Choosing greediness without identifying the extraction goal.

    The two forms have different stopping preferences.

    Fix: Decide first whether the task needs the first match or the last match.

  • Debugging only the final substring instead of the matching path.

    The result becomes easier to explain when you track how far the quantifier expanded and where it tested the remaining pattern.

    Fix: Trace expansion, the remainder check, and any return to an earlier stopping point.

Key Takeaways

  1. Greedy quantifiers expand toward the last valid stopping point.
  2. Non-greedy quantifiers stop at the first point where the rest of the pattern can be satisfied.
  3. Append ? to a quantifier to make it non-greedy, as in .+? and .*?.
  4. Backtracking means the engine can return to an earlier stopping point when the complete pattern is not satisfied.
  5. Choose greediness according to the extraction goal: first match or last match.

Key Takeaways

  • 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.