Concepts / Character Classes and Escape Sequences in Regex

Character Classes and Escape Sequences in Regex

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

  • Programming

The Stopping-Point Choice

A quantifier can face several places where a pattern might stop. The important distinction is whether it expands as far as possible or stops at the first point that allows the rest of the pattern to succeed. Greedy quantifiers expand toward the last valid occurrence. Non-greedy quantifiers stop at the first valid occurrence.

What do you think happens?

Suppose a pattern using .+ is applied to text containing several @ symbols, with the @ treated as the rest of the pattern. Where will .+ stop?

  • At the first @ symbol
  • At the last valid @ symbol
  • At the middle @ symbol
Reveal answer

Answer: At the last valid @ symbol

The greedy quantifier initially consumes as much as it can. It reaches the end of the string and then settles at the last valid stopping point where the remaining pattern is satisfied.

Tracing Greedy Expansion

expandkeep consumingsettle hereitem1characters consumed@first possible endpoint@later endpoint@last valid endpoint
How does a greedy quantifier extend its match from the first possible endpoint to the last valid endpoint?

To understand greedy matching, imagine the quantifier making a stopping-point decision. With .+, the engine initially matches as much as it can, continuing character by character until it reaches the end of the string. It then checks whether the rest of the pattern is satisfied. If the rest is satisfied, the quantifier settles at the last valid stopping point. When nothing follows the quantifier, reaching the end can complete the match.

A Greedy Match Across Several Delimiters

Consider .+ applied to text containing several @ symbols.

Begin: The .+ quantifier begins matching characters.

Reach the first @: The first @ is a possible stopping point, but the greedy quantifier does not stop there.

Continue expanding: The quantifier keeps matching character by character because it is trying to consume as much as possible.

Reach the end: After reaching the end, the engine checks whether the rest of the pattern is satisfied.

Settle: The match settles at the last valid stopping point.

The greedy form selects the later, last valid occurrence rather than the first possible occurrence.

Making a Quantifier Non-Greedy

A non-greedy quantifier stops as soon as the rest of the pattern can be satisfied. Append a question mark to a quantifier to make it non-greedy: use .+? instead of .+, and .*? instead of .*.

expands tostops attextitem1 @ item2 @ item3.+last valid @.+?first valid @
Given multiple possible delimiters, which endpoint does each quantifier choose?

The question mark changes the quantifier's stopping behavior. It does not remove the one-or-more behavior described for .+; instead, it makes the match stop as soon as the rest of the pattern can be satisfied. This changes the selected endpoint from the later valid occurrence to the earliest valid occurrence.

Following the Engine's Tests

greedy continuessettles at last valid pointnon-greedy succeedsfirst endpointpossible matchexpandgreedy choicelast endpointvalid matchstopnon-greedy choice
As the engine tests successive endpoints, what happens when the current choice succeeds or when greedy matching continues?

A useful debugging method is to list the possible endpoints in order. For a greedy quantifier, the engine keeps expanding rather than accepting the first possible endpoint. For a non-greedy quantifier, the engine stops at the first endpoint where the rest of the pattern can be satisfied. This endpoint trace explains why the two forms can return different substrings from the same input.

Extracting Individual Items

GoalPattern formSelected endpoint
Select through the last valid occurrence.+ or .*The last valid stopping point
Select the first valid occurrence.+? or .*?The first valid stopping point

The source example uses .+?@ with an email list. The pattern matches from the beginning of the string up to the first @ sign, the one in stephen.marquard@uct.ac.za. This is the useful behavior when the task is to extract an individual item before the first delimiter rather than consume across later delimiters.

For extraction tasks involving multiple delimiters, non-greedy matching is often safer because it selects one item at a time. Greedy matching is appropriate when the goal genuinely requires the later or last valid occurrence. The choice should follow the extraction goal: first match or last match.

Mistakes with Match Length

  • Assuming that .+ always stops at the first possible delimiter.

    The .+ form is greedy. It expands as much as possible and settles at the last valid stopping point.

    Fix: Use .+? when the intended endpoint is the first valid delimiter.

  • Adding a question mark without understanding what it changes.

    The question mark changes the quantifier from greedy to non-greedy, so the selected endpoint changes.

    Fix: Trace the possible endpoints and decide whether the task needs the first or last valid occurrence.

  • Choosing greediness without considering the extraction goal.

    The source distinguishes between goals that need the first match and goals that need the last match.

    Fix: Choose non-greedy for an individual item when the first delimiter is the intended boundary, and choose greedy when the later or last valid occurrence is required.

A match can appear to be too long not because the quantifier is failing, but because it is behaving greedily as designed. Inspect the pattern for .+ or .* and compare it with the non-greedy alternatives .+? or .*?. Then identify the first and last valid stopping points before deciding which form fits the task.

Practice the Endpoint Trace

EASY

A text contains multiple @ symbols. Decide whether .+ or .+? is the better choice for each goal: selecting through the last valid @, selecting through the first valid @, and extracting an individual item from a list with several delimiters.

Hints
  • Greedy quantifiers expand toward the last valid stopping point.
  • Appending ? changes .+ to .+? and .* to .*?.
  • For an individual item separated by multiple delimiters, consider whether the first delimiter should end the match.

Checking Your Choice

Choose between .+ and .+? when the desired result ends at the first valid delimiter.

Identify the goal: The goal asks for the first valid endpoint, not the last one.

Compare the forms: .+ is greedy, while .+? is non-greedy.

Select the pattern: The non-greedy form matches the first point where the rest of the pattern can be satisfied.

Use .+? when the first valid delimiter should end the match.

Key Takeaways

  1. Greedy quantifiers expand toward the last valid occurrence.
  2. Non-greedy quantifiers stop at the first valid occurrence.
  3. Append ? to convert .+ to .+? or .* to .*?.
  4. Trace possible endpoints to debug why a match is longer or shorter than expected.
  5. Choose greediness according to the task: first match or last match.

Key Takeaways

  • Greedy matching keeps expanding and settles at the last valid stopping point.
  • Non-greedy matching stops as soon as the rest of the pattern can be satisfied.
  • Appending a question mark converts greedy forms such as .+ and .* into non-greedy forms such as .+? and .*?.
  • Non-greedy matching is often safer when extracting individual items from text with multiple delimiters.
  • When debugging, identify the possible endpoints and compare the endpoint required by the task with the endpoint selected by the quantifier.