W3docs

Greedy and Lazy Quantifiers

Learn how greedy and lazy quantifiers work in JavaScript regular expressions: greedy matching consumes the maximum then backtracks.

A quantifier like *, +, or ? tells a regular expression how many times the preceding pattern may repeat. But when several different lengths of text would all satisfy the pattern, the engine has to decide which one to take. That decision is what greedy and lazy quantifiers control.

By default every quantifier is greedy: it grabs as many characters as it possibly can. Add a ? after the quantifier and it becomes lazy: it grabs as few as it can. Choosing the wrong mode is one of the most common regex bugs — the classic symptom is a pattern that "matches too much." This page explains the mechanism behind both modes so you can reach for the right one deliberately.

How greedy matching actually works: consume, then backtrack

A greedy quantifier does not magically know where to stop. It works in two phases:

  1. Consume the maximum. .* first swallows the entire rest of the string.
  2. Backtrack. If the pattern that follows .* can no longer match (because everything is already eaten), the engine gives characters back one at a time, retrying after each, until the whole pattern fits.

So greedy means "take everything, then reluctantly hand back the minimum needed to make the rest of the pattern succeed." Understanding the backtracking step is the key to predicting what greedy patterns do.

Greedy * in action


javascript— editable

Here .* matches any character zero or more times. Because there is nothing required after it, no backtracking is needed and it keeps everything to the end of the line, producing "ABCD*E".

Greedy + in action


javascript— editable

C+ matches "C" one or more times and greedily takes all three, so the match is "ABCCC".

How lazy matching works: consume the minimum, then expand

A lazy quantifier inverts the strategy:

  1. Consume the minimum. .*? starts by matching nothing.
  2. Expand. Only if the rest of the pattern fails to match does the engine let the lazy quantifier take one more character, then it retries — repeating until the whole pattern succeeds.

So lazy means "take as little as possible, and grow only when forced to." You make any quantifier lazy by appending ?.

Lazy *? in action


javascript— editable

This is the confusing case. The result is just "AB". Why? Because .*? is allowed to match nothing, and there is nothing after it in the pattern that forces more consumption. As soon as AB matches, the pattern is already complete, so the lazy quantifier happily stops at zero characters. A lazy quantifier only expands when something after it — a delimiter, a literal, or an anchor — demands it.

Lazy +? in action


javascript— editable

C+? must match at least one "C" (that is what + requires), and nothing after it asks for more, so it stops at the first one: "ABC".

The canonical example: <.*> vs <.*?>

The difference between greedy and lazy is easiest to see when there is something after the quantifier. Matching HTML tags is the textbook case. Run both patterns against the same string:


javascript— editable
  • Greedy /<.*>/ matches "<p>Hello</p>" — the whole string. .* eats everything, then backtracks just far enough to leave a > for the final > in the pattern, landing on the last >.
  • Lazy /<.*?>/ matches only "<p>" — a single tag. .*? expands character by character and stops the instant it reaches the first >.

When your goal is "match one tag," "match one quoted string," or "match up to the next delimiter," lazy is almost always what you want.

The full lazy quantifier family

Every greedy quantifier has a lazy twin formed by adding ?:

GreedyLazyMeaning of the lazy form
**?Zero or more, as few as possible
++?One or more, as few as possible
???Zero or one, prefer zero
{2,5}{2,5}?Between 2 and 5, prefer 2
{2,}{2,}?At least 2, prefer 2

Note that ?? is not a typo: the first ? is the quantifier (zero or one) and the second makes it lazy, so it prefers to match nothing when it has a choice.


javascript— editable

When should you use lazy quantifiers?

A practical rule:

Use a lazy quantifier when you want to match up to the first occurrence of a delimiter, and greedy when you want everything up to the last.

Common situations where lazy is the right call:

  • Extracting a single HTML/XML tag: /<.*?>/.
  • Capturing the contents of one set of quotes or brackets: /".*?"/, /\(.*?\)/.
  • Grabbing text up to the next separator without overshooting into the following record.

Two important caveats:

  • A delimiter is often clearer than laziness. Instead of /".*?"/ you can write /"[^"]*"/ with a negated character class. This avoids backtracking entirely and is usually faster and more predictable.
  • Lazy needs something to stop on. As the AB.*? example showed, a lazy quantifier at the end of a pattern (with nothing forcing it forward) collapses to its minimum and matches almost nothing. Pair it with a following literal, anchor, or capturing group.

Summary

  • Quantifiers are greedy by default — they take the maximum, then backtrack to make the rest of the pattern fit.
  • Append ? to make a quantifier lazy — it takes the minimum, then expands only when forced.
  • A lazy quantifier with nothing after it matches as little as it legally can (often nothing), so always give it a delimiter or anchor to stop on.
  • The full lazy family is *?, +?, ??, and {n,m}?.
  • Reach for lazy when you want "up to the first" delimiter; otherwise a negated character class is often the cleaner, faster choice.

Practice

Practice
Given the string '<p>Hi</p>', what does the lazy pattern /<.*?>/ match?
Given the string '<p>Hi</p>', what does the lazy pattern /<.*?>/ match?
Was this page helpful?