Skip to content

Quantifiers: how many, and how greedy

Quantifiers repeat the thing before them, and by default they take as much as they can.

Lesson 3 of 4 · about 3 minutes

The four you will use

A quantifier repeats whatever is immediately before it: a character, a class, or a group. ? means none or one, * means none or more, + means one or more, and {2,5} means between two and five. {3} means exactly three, and {2,} means two or more.

Because a quantifier attaches to the thing before it, ab+ means an a followed by one or more b, not one or more of "ab". That needs a group: (ab)+.

Greedy by default

Quantifiers take as much as they can and give back only when the rest of the pattern cannot match. This is the single most common cause of a pattern that "matches too much".

The classic case is matching a tag with <.+>. Against <b>hello</b>, .+ first swallows everything to the end, then backs up until a > can match — which lands on the final one, so the whole string matches rather than just <b>.

Adding a ? after the quantifier makes it lazy: it takes as little as possible and grows only when forced. <.+?> matches <b> as intended. The alternative is to say what you actually mean — <[^>]+> matches "anything that is not a closing bracket", which is both faster and clearer about its intent.

When a quantifier becomes a performance problem

Nested quantifiers over overlapping character sets can make an engine explore an enormous number of ways to split the same text. The usual demonstration is (a+)+$ against a long run of a characters followed by something that cannot match: the engine tries every combination before giving up.

This is called catastrophic backtracking, and it is a denial-of-service risk whenever a pattern comes from a user. Prefer specific classes over . when you can, avoid a quantifier directly inside another, and run untrusted patterns somewhere you can abandon them. The regex tester on this site runs every pattern in a worker with a timeout for exactly this reason.

Worked examples

  • Watch a greedy quantifier take too much

    /<.+>/g

    Against: <b>hello</b>

    One match, the whole string. The dot-plus reaches the end and backs up to the last >.

  • The same pattern, made lazy

    /<.+?>/g

    Against: <b>hello</b>

    Two matches, <b> and </b>. <[^>]+> gets the same result without relying on laziness.

Check yourself

Practice questions written for this lesson — not past exam papers.

Practise every question in this subject

  1. What does ab+ match?

  2. Why does <.+> match the whole of <b>hello</b>?

Try it