Regexdrill

Syntax Updated November 2026

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.

Previous: Alternation |Next: Word boundary \b