Greedy vs. Lazy Regex Matching: Why Your Pattern Matches Too Much
<.+> looks like it should match one HTML tag. Run it against <b>bold</b> and it matches the entire string, tags and all, instead of stopping at the first >. That's not a bug in the regex engine — it's greedy matching doing exactly what it's designed to do, and it's the single most common reason a pattern that "obviously" should work doesn't.
Greedy quantifiers grab as much as possible, then backtrack
By default, *, +, and {n,} are greedy: they try to match as many characters as possible first, and only give characters back if the rest of the pattern fails to match otherwise. <.+> against <b>bold</b> greedily consumes everything up to the last > in the string, because .+ will happily eat through </b> and bold too — it only backs off if forced to.
This is invisible on short test strings where there's only one > to find, and only becomes obvious once real data has more than one instance of the closing character.
Lazy quantifiers stop at the first match that works
Adding a ? after a quantifier makes it lazy instead: <.+?> tries to match as few characters as possible, expanding only when the rest of the pattern demands it. Against the same string, <.+?> stops at the very first > it can — matching just <b>, not the whole tag soup.
The rule of thumb: if a pattern is matching more than you expect, especially across multiple similar delimiters, the fix is almost always adding ? after the greedy quantifier that's overreaching.
When greedy is actually what you want
Greedy isn't wrong by default — it's wrong when there's more than one instance of your closing character in the string. It's the right choice when:
- You're matching to the last occurrence of something on purpose (trimming trailing whitespace with
\s+$, for example). - There's genuinely only one possible closing delimiter in valid input.
- Performance matters and you've confirmed backtracking isn't a problem — lazy quantifiers can be slower on some inputs because they check more incrementally.
A quick test to catch the bug before it ships
Run the pattern against a string with two instances of your delimiter, not one. <b>bold</b> and <i>italic</i> will immediately expose a greedy <.+> matching from the first < to the last >, spanning both tags — the exact failure mode that a single-tag test string hides.
Try it
The Regex Tester highlights every match live as you type, so a greedy pattern eating more than intended is visible immediately instead of surfacing later against production data.
Hanuman Singh · built snaptxt.app · hanumansingh.dev