You write a pattern to grab a short piece of text, run it, and the match swallows half the document. Nothing is wrong with your pattern's spelling. The problem is greediness: by default, quantifiers like * and + match as much text as they possibly can while still allowing the rest of the pattern to succeed. Once you see that behaviour on a real example, the fix stops feeling mysterious. Regex Tester shows matches highlighted in your sample text with capture groups listed, which makes the difference between greedy and lazy matching visible instead of theoretical.

Start with a simple case. Suppose you have a fictional product note, invented for this example, and you want the first quoted phrase:

The "linen apron" and the "sewing kit" are both in stock.

The natural first pattern is ".*" — a quote, any characters, then a quote. A beginner expects it to match "linen apron". It actually matches "linen apron" and the "sewing kit", from the first quote to the last quote in the line. The .* did exactly what it was told: it took as many characters as possible, then gave back just enough for the final quote to match. That giving-back process is called backtracking, and it is the reason greedy patterns so often overshoot.

Adding a question mark changes the question

The lazy version of the same pattern is ".*?". The question mark after the quantifier does not mean "optional" here; it means "match as few characters as possible". With that one character added, the pattern matches "linen apron" and stops, because the shortest match that satisfies the pattern is the correct one for this job. Run both patterns against the same text and the highlighted matches tell the story instantly: one long span, then one short span.

Lazy quantifiers have their own version of the same trap. A lazy pattern can undershoot when you actually wanted everything up to a later marker. Consider extracting the content of a fictional HTML-style tag pair:

<note>first</note> and <note>second</note>

A greedy <note>.*</note> matches the whole line, from the first opening tag to the last closing tag. A lazy <note>.*?</note> matches <note>first</note> on its first match, and a global search finds the second one too. For repeated elements, lazy is usually what you want. For "everything between the first marker and the last marker", greedy is correct. The quantifier is not good or bad on its own; it answers a different question in each case, and the bug is asking the wrong one.

Worked example: pulling prices from a fictional list

Here is a small fictional price list, invented for this example, with no real products or sellers:

item: "canvas tote" price: 18; item: "linen apron" price: 24; item: "sewing kit" price: 12

A writer wants each quoted item name. The greedy pattern ".*" matches from the first quote to the last quote, returning one giant match containing all three names plus the prices in between. That is useless for a list. The lazy pattern ".*?" with a global search returns three matches: "canvas tote", "linen apron", and "sewing kit". Each match is exactly one name, and the tester shows them separately.

Now suppose the writer instead wants everything from the first item to the last price, as a single block — perhaps to move the whole list. The greedy pattern is suddenly the right tool, because the desired result is the longest span. Testing both versions against the same text, rather than guessing which you need, takes seconds and removes the most common source of regex frustration. If the pattern also needs to capture the numbers, capture groups help: price: (\d+) captures each price separately, and the group table in the tester shows the captured digits without the surrounding label.

Three habits that prevent greedy surprises

First, test with text that contains two of whatever you are matching, not one. A pattern tested against a single quoted phrase cannot reveal greediness, because there is no second quote for it to overshoot to. Two items in the sample text expose the behaviour immediately. Second, anchor your patterns where you can. If the match should end at a specific character, say so: [^"]* (any characters except a quote) matches a quoted phrase without any greediness question at all, because a quote cannot be part of the match. Character classes like this are often clearer than lazy quantifiers, and they run faster too.

Third, use the replace preview before applying a pattern to real data. A greedy pattern in a find-and-replace can delete far more than intended, and the preview shows the result before anything is changed. This matters most with patterns applied to documents rather than short strings. A pattern that looks right on one line can behave very differently across a whole file, especially when the dot matches characters you did not expect. For a deeper grounding in safe patterns, see the regex safety guide, which covers the performance dangers that greediness can create when combined with nested quantifiers.

Honest limitations

A tester shows you what a pattern does on the sample text you provide. It cannot prove the pattern is correct for text you have not tested, and regex flavours differ: a pattern written for JavaScript, which this tester uses, may behave differently in another language, particularly around features like lookbehind. Also, a pattern that matches correctly is not necessarily a good pattern. A lazy quantifier can still be slow on long inputs, and a pattern full of overlapping alternatives can become hard to read. Test with realistic samples, including edge cases like empty strings and repeated markers, and prefer the simplest pattern that gives the right matches.

FAQs

What does greedy mean in regex?

A greedy quantifier matches as much text as possible while still letting the rest of the pattern succeed. .* will stretch to the last possible position, then give back characters only as needed for the remainder of the pattern to match.

How do I make a quantifier lazy?

Add a question mark after it: *? instead of *, +? instead of +. A lazy quantifier matches as few characters as possible, expanding only as needed for the rest of the pattern to succeed.

When should I use greedy instead of lazy?

Use greedy when you want the longest span, such as everything from the first marker to the last marker. Use lazy when you want the shortest span, such as each repeated element separately. If neither fits, a negated character class like [^"]* is often clearest.

Why does my pattern match the whole line instead of one item?

Almost always because a greedy quantifier stretched past the first closing marker to a later one. Test with two items in the sample, try the lazy version, and check the highlighted matches to see exactly where the match ends.

If your pattern lives inside structured data, JSON Studio can validate the surrounding file, and Text Compare can show what a replace operation changed, line by line.

human review pending client designation