Greedy vs. Non-Greedy Matching
A greedy quantifier expands as far as it can and settles on the last occurrence that still allows the pattern to succeed.
Try it: Regular expressions: a backtracking matcher
How Python's re module matches a pattern: it tries each start position, matches tokens one by one, lets greedy quantifiers take as much as possible and give it back when the rest fails (lazy ones take as little as possible), tries alternatives in order and records groups.
How it works
- search tries start positions 0, 1, 2 …; match tries only position 0; findall collects every non-overlapping match.
- Tokens are matched left to right: literals, ., classes like [a-c] and \d, and zero-width anchors ^, \$, \b.
- A greedy quantifier (* + ? {m,n}) takes as many repetitions as it can, then backtracks one at a time; a lazy one (*? +? ??) takes as few as possible and grows only when needed.
- Alternatives in a | b are tried in order; the first that lets the whole pattern match wins.
- Parentheses capture the text their part matched; captures are undone when the matcher backtracks past them.
Default run (63 steps): re.search('(\\w+)@(\\w+)\\.com', 'mail bo@ikb.com now'): try each start position until one matches. … re.search('(\\w+)@(\\w+)\\.com', 'mail bo@ikb.com now') → <re.Match object; span=(5, 15), match='bo@ikb.com'>
Simplified: A subset of re: no flags, lookarounds, backreferences, named groups or possessive quantifiers; pattern and text up to 24 printable ASCII characters. The trace stops after 1900 attempts ("too many steps") where real Python would keep backtracking.
Loading the simulation…
The Stopping-Point Problem
Regular-expression patterns often have more than one possible place where they could stop. A greedy quantifier expands as far as it can and settles on the last occurrence that still allows the pattern to succeed. A non-greedy quantifier stops at the first occurrence that satisfies the rest of the pattern. The $ anchor adds a different kind of constraint: it requires the match to end at the end of a line.
What do you think happens?
Suppose a pattern uses .+ before an @ symbol in a string containing several @ symbols. Will .+ normally stop at the first @ or continue toward the last possible @?
Reveal answer
It continues toward the last possible @.
The greedy quantifier .+ expands as much as possible. It settles at the last valid stopping point for which the remaining pattern can still succeed.
Greedy Expansion
The plus quantifier means one or more characters. When it is written as .+, the dot-and-plus combination is greedy. It initially consumes as much text as possible, then settles at the last position where the rest of the pattern can still be satisfied. If the pattern is .+ followed by @, the greedy portion expands toward the last usable @ rather than stopping at the first one.
Choosing the Match Around @ Symbols
Compare .+@ and .+?@ when the text contains the email list example stephen.marquard@uct.ac.za.
- 1Greedy pattern
The .+ portion expands as far as possible before the @ that completes the pattern. It therefore aims for the last valid @ symbol in the available text.
- 2Non-greedy pattern
Adding ? changes .+ to .+?. The quantifier stops as soon as the rest of the pattern can succeed, so it aims for the first @ symbol.
- 3Selection rule
Use the greedy form when the last valid occurrence is the intended boundary. Use the non-greedy form when the first valid occurrence is the intended boundary.
Greedy and non-greedy forms use the same basic repetition, but they choose different stopping points.
The Line Ending Anchor
The $ symbol is a positional anchor that marks the end of a line. It does not match a literal dollar-sign character. A pattern such as end$ matches end only when end appears at the line ending.
The anchor changes where a successful match is allowed to finish. In This is the end, end$ can match because end is at the line ending. In end of the story, end$ does not match because additional characters follow end.
Greedy Matching at Line End
A greedy quantifier and the $ anchor can work together. In [0-9.]+$, the character class must match one or more digits or literal periods, and the complete match must reach the line ending. Because the match must finish at the end, the greedy quantifier expands through the final sequence that can satisfy the character class and the anchor.
| Pattern | Position requirement | Extraction behavior |
|---|---|---|
| [0-9.]+ | No line-ending requirement | Can match an eligible sequence encountered earlier |
| [0-9.]+$ | Must finish at the line ending | Targets an eligible sequence that extends to the line end |
An open-ended character-class pattern and the same pattern with a line-ending anchor serve different extraction goals.
Literal Periods in Character Classes
A period outside a character class can have wildcard behavior in regular-expression patterns. Inside square brackets, however, the period loses that wildcard meaning and matches only a literal period. Therefore, [0-9.]+ is suitable for sequences made from digits and periods, such as 0.8475.
The brackets are not decorative: they define a set of allowed characters. In [0-9.]+, the set contains digits and the literal period, so the class does not treat every character as acceptable.
Searching Before Extracting
A useful structured pattern can first identify the shape of a line and then extract the value at its end. The source pattern begins with X, allows any characters in between, requires a colon and a space, and finishes with [0-9.]+$. The final anchor ensures that the digits-and-periods portion continues through the line ending rather than stopping at an earlier eligible sequence.
Selecting the End Value
A structured line contains an earlier digit sequence and a confidence value at the end. Compare an open-ended [0-9.]+ pattern with [0-9.]+$.
- 1Open-ended search
Without $, [0-9.]+ is not required to finish at the line ending, so it can match the first eligible digit-and-period sequence encountered.
- 2Anchored search
With $, the eligible sequence must extend to the line ending. The match therefore targets the final value when that value is made from digits and periods.
- 3Extraction decision
The anchored form is appropriate when the data of interest is consistently located at the end of each structured line.
Adding $ changes the positional requirement from anywhere in the line to the line ending.
Choosing the Quantifier
| Goal | Useful choice | Reason |
|---|---|---|
| Reach the last valid occurrence | Greedy quantifier such as .+ | The quantifier expands as far as possible while allowing the pattern to succeed |
| Stop at the first valid occurrence | Non-greedy quantifier such as .+? | The question mark makes the quantifier stop as soon as the rest of the pattern can succeed |
| Require a value at the line ending | An end anchor such as [0-9.]+$ | The match must finish at the line ending |
| Match data without caring about its line-ending position | An open-ended pattern without $ | No end-of-line constraint is added |
Greediness controls how far a repeated part expands; $ controls where the complete pattern must end.
Common Matching Mistakes
Common mistake Treating $ as a literal dollar-sign character
What it looks likeUsing $ when the intended meaning is a currency symbol
Why it failsIn regular expressions, $ is a positional anchor marking the end of a line.
Do this insteadInterpret $ as an end-of-line requirement in this context.
Common mistake Using an open-ended pattern when the desired value is at the line ending
What it looks like[0-9.]+Why it failsThe pattern is not required to continue through the line ending, so it may match an earlier eligible sequence.
Do this insteadUse [0-9.]+$ when the digits-and-periods value must reach the end of the line.
Common mistake Assuming the period inside [0-9.] is a wildcard
What it looks likeExpecting [0-9.]+ to accept any character between digits
Why it failsInside square brackets, the period matches only a literal period.
Do this insteadRead [0-9.] as a character class containing digits and the literal period.
Common mistake Using a greedy quantifier when the first delimiter is the intended boundary
What it looks like.+@Why it failsThe greedy .+ expands toward the last valid @.
Do this insteadUse .+?@ when the intended boundary is the first @.
Common mistake Using a non-greedy quantifier when the last occurrence is required
What it looks like.+?@Why it failsThe non-greedy form stops at the first @ that allows the pattern to succeed.
Do this insteadUse a greedy form such as .+@ when the last valid occurrence is the intended stopping point.
Practice the Decision
For each situation, choose the more suitable pattern form: a greedy quantifier, a non-greedy quantifier, an open-ended character class, or the same character class followed by $. Then explain whether your goal is the first valid occurrence, the last valid occurrence, or a value that reaches the line ending.
Hints
- Ask whether the pattern should stop at the first or last valid delimiter.
- Ask whether the extracted value must be at the end of the line.
- Remember that adding ? to a quantifier makes it non-greedy.
- Remember that a period inside [0-9.] is literal.
- 1Use greediness to control which valid occurrence becomes the stopping point. Use $ to control where the complete match must finish. These are separate decisions: a pattern can be greedy without being end-anchored, or it can combine a greedy character class with $ to extract a value that extends to the line ending.
Key Takeaways
- $ marks the end of a line in a regular expression; it does not match a literal dollar sign.
- Greedy quantifiers expand toward the last valid occurrence, while non-greedy quantifiers stop at the first valid occurrence.
- Appending ? changes a greedy quantifier such as .+ or .* into a non-greedy form such as .+? or .*?.
- The pattern [0-9.]+$ targets a sequence of digits and literal periods that reaches the line ending.
- Inside a character class, the period matches a literal period rather than acting as a wildcard.