Regex Greedy vs Lazy Matching Explained (2026)
Photo by Unsplash on Unsplash
Table of Contents
The Short Version
This is behind one of the most common regex frustrations: 'why is my pattern matching way more than I wanted?' Nine times out of ten, the answer is a greedy quantifier gobbling up text you expected it to leave alone. Once you understand greedy versus lazy, you gain precise control over how much a pattern consumes, and a whole category of baffling regex behavior suddenly makes sense. It's a small concept with an outsized payoff.
What 'Greedy' Actually Means
So `.*` doesn't mean 'match a little'; it means 'match absolutely everything you can, then hand back the minimum needed to make the whole pattern work.' That backtracking step is easy to forget, but it's central. The engine is greedy first and reluctant second: it overreaches on purpose, then walks back just enough. Understanding that two-phase behavior — grab everything, then retreat as required — is the key to predicting what a greedy pattern will actually capture, which is often more than beginners expect.
The Classic Example
Now make it lazy: `<.*?>`. The `?` after `.*` tells the engine to match as few characters as possible. This time it matches just `<b>`, stops at the first `>`, and if you keep searching it finds `</b>` as a separate match. Same input, one extra character in the pattern, completely different result. This tag example is the canonical demonstration for a reason — it shows greedy overreach and the lazy fix side by side in a way you won't forget.
How to Make a Quantifier Lazy
It's worth being careful about the double meaning of `?` here, because it does two different jobs. On its own, `?` means 'zero or one of the preceding thing.' Placed after another quantifier, it means 'be lazy.' So `a?` matches an optional `a`, while `a+?` matches one-or-more `a`s lazily. Context tells you which role the `?` is playing. If regex fundamentals are still shaky for you, my walkthrough on writing your first regex pattern covers the basics that make this distinction easier to absorb.
When to Use Greedy vs Lazy
Greedy matching is the right default when you genuinely want to consume as much as possible, such as trimming everything after a certain point or matching a whole line. Often greedy is simply fine and you never think about it. The trouble only starts when you *assume* a quantifier will stop early and it doesn't. My rule of thumb: if a pattern is capturing more than you intended and there's a repeated delimiter involved, try making the quantifier lazy and see if it snaps to what you wanted. It usually does. A concrete case I hit often is pulling one query parameter out of a URL: greedy will happily run past the delimiter you meant to stop at, so lazy is usually what you want there. If you're working with URLs a lot, it pairs naturally with understanding URL percent-encoding, since the two problems tend to show up together.
Beware Catastrophic Backtracking
It's a real security concern: attackers deliberately craft inputs to trigger it, a technique known as a regex denial-of-service. The defenses are to avoid nested quantifiers where possible, be specific instead of leaning on broad `.*` patterns, and test your regexes against nasty inputs. Switching to lazy matching doesn't automatically fix catastrophic backtracking, but writing tighter, more specific patterns generally does. When a regex mysteriously hangs, backtracking is almost always the culprit, and it's worth reworking the pattern rather than just throwing more timeout at it.
Test Before You Trust
Interactive regex testers that highlight matches in real time are invaluable here — you paste your pattern and some sample text, and you can literally watch a greedy quantifier swallow more than a lazy one would. Seeing the highlight expand and contract as you add or remove a `?` teaches the concept faster than any explanation. Excellent free references like MDN's regular expressions guide and community tester sites are worth keeping handy. Test with real, varied data, and greedy-versus-lazy surprises stop reaching production.
The Takeaway
Use lazy when you want the smallest match up to the nearest delimiter, use greedy when you genuinely want to consume as much as possible, and stay alert to catastrophic backtracking with broad or nested patterns. Master this one distinction and you'll fix the majority of 'my regex matches too much' problems yourself, without the trial-and-error flailing that makes people dread regular expressions in the first place.
Frequently Asked Questions
What is the difference between greedy and lazy in regex?
A greedy quantifier matches as much text as possible while still letting the pattern succeed, then backtracks if needed. A lazy (non-greedy) quantifier, made by adding a ? after the quantifier, matches as little as possible. Greedy grabs everything it can; lazy stops at the first opportunity.
How do I make a regex quantifier lazy?
Add a ? immediately after the quantifier. So * becomes *?, + becomes +?, and {2,} becomes {2,}?. The trailing ? flips the behavior from 'as much as possible' to 'as little as possible.' For example, <.*?> matches a single tag instead of everything between the first and last bracket.
Why does my regex match too much?
Almost always because a quantifier like .* is greedy and consuming more than you expected, running all the way to the last possible delimiter. Making it lazy with .*? usually fixes it by stopping at the first delimiter. This is the most common regex surprise for beginners.
What is catastrophic backtracking?
It's a performance problem where greedy quantifiers, especially nested ones like (a+)+, force the regex engine into an enormous number of backtracking attempts on certain inputs, potentially freezing it. Attackers can exploit it as a denial-of-service. Avoid nested quantifiers and write specific patterns to prevent it.
When should I use greedy vs lazy matching?
Use lazy when you want the smallest chunk, like extracting content between delimiters or inside quotes. Use greedy when you genuinely want to consume as much as possible, like matching a whole line. If a pattern grabs too much around repeated delimiters, try lazy. See my guide on [writing your first regex](/blog/what-is-regex-how-to-write-first-pattern).
Try ToolsFuel
23+ free online tools for developers, designers, and everyone. No signup required.
Browse All Tools