iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Quantifiers

Quantifiers control how many times the previous element matches. ? = 0-1, * = 0+, + = 1+, {n,m} = bounded. Add ? after to make them lazy / non-greedy.

Greedy vs lazy, possessive, backtracking

EXAMPLE
// 1) Basics
/a?/      // 0 or 1 'a'
/a*/      // 0+ 'a'
/a+/      // 1+ 'a'
/a{3}/    // exactly 3
/a{3,}/   // 3 or more
/a{3,5}/  // 3 to 5

// 2) Greedy by default — match as much as possible
'<a>b</a>'.match(/<.+>/);     // ['<a>b</a>']  — greedy: spans both tags

// 3) Lazy — match as little as possible (add ? after the quantifier)
'<a>b</a>'.match(/<.+?>/);    // ['<a>']      — stops at first '>'

// 4) Possessive — match as much as possible, no giving back (PCRE / .NET; not in JS by default)
/^a++b$/    // PCRE: possessive +; in JS use atomic group (?>...) or rewrite to avoid backtracking

// 5) The catastrophic backtracking trap
// /(a+)+b/ tested against 'aaaaaaaaaaaaaaaa!' — exponential blowup
// The engine tries every split of the 'a's between the inner + and outer + before failing.
// Avoid: don't nest quantifiers on overlapping sets.

// FIX — atomic group or unique sub-patterns
//   PCRE / .NET / Python: (?>a+)+b
//   JS:                    /a+b/  (rewrite — the nested + was redundant)

// 6) Quantifier on a group
/(ab){3}/.test('ababab')       // true — 'ab' three times
/(ab)+c/.test('ababc')         // true

// 7) Real recipes

// 7a) Match a number (integer, possibly signed)
/^-?\d+$/.test('42')          // true
/^-?\d+$/.test('-42')         // true
/^-?\d+$/.test('+42')         // false (no + prefix)
/^[+-]?\d+$/.test('+42')      // true

// 7b) Decimal
/^-?\d+(\.\d+)?$/.test('3.14')
/^-?\d+(\.\d+)?$/.test('3.')        // false
/^-?\d+(?:\.\d+)?$/             // non-capturing group via (?:...)

// 7c) Phone (loose)
/^\+?[\d\s()-]{7,20}$/.test('+61 2 1234 5678')

// 7d) URL-ish (do not use for validation — use new URL())
/^https?:\/\/[^\s"<>]{1,2000}$/

// 7e) HTML tag (do not use for parsing — use a parser)
/<\/?[a-z][^>]*>/gi

// 7f) Repeated whitespace collapse
'   hello   world   '.replace(/\s+/g, ' ').trim();

// 8) Quantifiers + character classes
/^[\w-]+$/                     // letters, digits, _, -
/^[A-Za-z]{2,4}$/              // 2-4 letters
/^[01]+$/                       // binary

// 9) Avoid \d at scale — Unicode
// \d matches [0-9] in most engines, but in some modes it includes Arabic-Indic, etc.
// For ASCII-only digits, use [0-9].

// 10) Quantifier-anchored patterns
/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}$/    // strong password — see lookaround lesson

// 11) Performance + safety
//   • Use atomic groups / possessive when supported to neutralise backtracking
//   • Anchors (^ $ \b) prune the search space — much faster
//   • Replace .* with [^X]* when you know what can't appear
//   • In adversarial input, regex DoS (ReDoS) is real — test with long worst-case strings
//   • Use RE2 (Go, ripgrep) when you can — linear-time guarantee

// 12) Test patterns at regex101.com — visualise quantifier behaviour + spot lazy/greedy traps

// 13) Cheat sheet
//   ?           - 0 or 1                       (lazy: ??)
//   *           - 0 or more                    (lazy: *?)
//   +           - 1 or more                    (lazy: +?)
//   {n}         - exactly n                    (no lazy variant — already exact)
//   {n,}        - n or more                    (lazy: {n,}?)
//   {n,m}       - between n and m              (lazy: {n,m}?)
//   Possessive (PCRE):
//   ?+ *+ ++ {n,m}+   - no backtracking inside this quantifier

Why it matters

Default quantifiers are greedy — the most common bug is /<.+>/ swallowing past the first >. Add ? to go lazy, or use a negated class ([^>]+) for clarity and speed.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
x?          // 0 or 1
x*          // 0 or more
x+          // 1 or more
x{3}        // exactly 3
x{2,5}      // 2 to 5
x*?         // lazy (smallest match)
x*+         // possessive (PCRE/Java — no backtracking)
Try it Yourself »

Exercise

Quantifier for "one or more".

/a /

Test yourself

Q1. x+ means…
Q2. A lazy quantifier is denoted by appending…
Q3. {2,5} matches…

Discussion

Loading…