/glossary/regex/greedy-vs-lazy-quantifiers
Greedy vs lazy quantifiers in regex
verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash) · grep (GNU grep) 3.0updated 2026-10-20
- tool
- Regex
- versions
- PCRE, Python, JavaScript
- os
- any
Quantifiers (*, +, ?, {n,m}) are greedy by default: they match as many characters as possible, then give some back (backtrack) only if the rest of the pattern would fail otherwise. Adding ? makes them lazy: *?, +?, ??, {n,m}? match as few characters as possible and take more only when needed.
The classic example
node - <<'EOF'
const html = '<b>bold</b> and <i>italic</i>';
console.log("greedy <.+> ", html.match(/<.+>/g));
console.log("lazy <.+?> ", html.match(/<.+?>/g));
console.log("class <[^>]+>", html.match(/<[^>]+>/g));
const csv = '"a","b,c","d"';
console.log("greedy \".*\" ", csv.match(/".*"/g));
console.log("lazy \".*?\" ", csv.match(/".*?"/g));
EOFOutput
greedy <.+> [ '<b>bold</b> and <i>italic</i>' ] lazy <.+?> [ '<b>', '</b>', '<i>', '</i>' ] class <[^>]+> [ '<b>', '</b>', '<i>', '</i>' ] greedy ".*" [ '"a","b,c","d"' ] lazy ".*?" [ '"a"', '"b,c"', '"d"' ]
The greedy <.+> runs to the last > on the line and returns one big match. The lazy <.+?> stops at the first > it can. A negated class, <[^>]+>, gives the same result as the lazy form without backtracking, and is usually the better choice.
In short
| Greedy | Lazy | Behaviour |
|---|---|---|
| * | *? | zero or more: as many / as few as possible |
| + | +? | one or more |
| ? | ?? | zero or one |
| {2,5} | {2,5}? | between 2 and 5 |
Laziness changes which match is found, not whether one is found. For parsing real HTML, JSON or CSV, use a parser; regexes break on nesting and escaping.
Sources
Related pages
cheat sheets · regexRegex cheat sheet: characters, quantifiers, groups and lookaroundsRegex cheat sheet: character classes, anchors, quantifiers, greedy and lazy matching, groups and backreferences, lookarounds, with tested Python examples.compat · regexRegex features by engine: JavaScript, Python, PCRE and POSIX EREWhich regex features work where: lookbehind, named groups, \p{L}, atomic groups and possessive quantifiers in JavaScript, Python re, PCRE and POSIX ERE, tested.flags · regexJavaScript regex flags: g, i, m, s, u, v, y and dWhat each JavaScript RegExp flag does: g finds all matches, i ignores case, m works per line, s lets . match newlines, u and v add Unicode, plus y and d.