Lazy vs greedy
Greedy quantifiers (*, +, {n,m}) match as much as they can and give back only if the rest of the pattern fails; lazy quantifiers (*?, +?, {n,m}?) match as little as possible and extend only when needed. On a1b2b, a.*b matches the whole string while a.*?b matches a1b.
Syntax
.* (greedy) .*? (lazy) [^x]* (often the better choice)Examples
"<b>one</b><b>two</b>".match(/<b>.*<\/b>/)[0]Result: "<b>one</b><b>two</b>"
Greedy: runs to the last closing tag.
"<b>one</b><b>two</b>".match(/<b>.*?<\/b>/)[0]Result: "<b>one</b>"
Lazy: stops at the first closing tag.
'say "hi" and "bye"'.match(/"[^"]*"/g)Result: ['"hi"', '"bye"']
A negated class does the same job without backtracking.
"aaa".match(/a+?/)[0]Result: "a"
Common mistakes
- Thinking lazy means shortest overall match: a.*?b still starts at the first a and ends at the first b after it.
- Adding a lazy quantifier before an end anchor, as in .*?$, which still has to consume everything.
- Using .*? for long inputs where [^x]* would do; lazy matching retries at every character and can be slow.
- Forgetting that the dot does not cross newlines, lazy or not; add the s flag for multi-line blocks.
Practice Lazy vs greedy
These drills check your answer on live data, free, no account needed.
- Lazy vs greedy: the first quoted textCapture the text inside the first pair of double quotes on the line in group 1. It can be empty.
- Strip HTML tagsRemove every HTML tag (anything from < to the next >) and keep the text between tags. A lone < with no closing > stays.
- Matching quote marksThe whole line must match. Match text wrapped in quotes, where the closing quote is the same kind as the opening one: both double or both single.
Questions
What does *? mean in regex?
Zero or more, as few as possible. The engine first tries zero repetitions and adds one at a time only while the rest of the pattern fails.
Is lazy or greedy faster?
Neither is always faster. Greedy with a negated class ([^>]*) usually beats lazy (.*?) because it never backtracks. Lazy is slow when the end marker is far away.
How do I match the shortest string between two words?
start(.*?)end with the s flag if it may span lines. For a single-character delimiter, prefer start([^x]*)end.
Related
- QuantifiersWhat * + ? {n} {n,} and {n,m} mean, how greedy matching works, how to repeat a group instead of a single character, and the silent {2, 3} mistake.
- Negated character classHow [^...] matches any character except the listed ones, stripping non-digits, grabbing quoted text, splitting on a delimiter, and how it differs from (?!).
- Regex for HTML tagsHow to remove HTML tags with <[^>]+>, list tag names, read an href value, match the content of one tag lazily, and why regex is not an HTML parser.
- Dot and newlineWhy . does not match line breaks by default, the s flag in JavaScript and re.DOTALL in Python, the portable [\s\S] trick, and how s differs from m.