Home/Blog/Article
general

Regex Match Between Two Characters: Lazy vs. Greedy Quantifiers

June 28, 20265 min readByAarav Mehta·Developer Tools Editor·Jun 2026
Regex Match Between Two Characters: Lazy vs. Greedy Quantifiers

One of the most common questions developers ask when first learning Regular Expressions is: "How do I extract the text between two specific characters?"

Whether you're trying to pull a value out of a JSON string, extract a substring between parentheses, or scrape text from inside an HTML tag, the solution almost always boils down to understanding quantifiers.

The Greedy Mistake: \`.*\`

Let's say you have the following string and you want to extract the text inside the brackets:

```text
The quick [brown] fox jumps over the [lazy] dog.
```

A beginner will typically write this pattern:
```regex
[.*]
```

Open in Sandbox

If you run this in our sandbox, you'll see a massive problem. Instead of matching `[brown]` and `[lazy]` separately, it matches the entire string: `[brown] fox jumps over the [lazy]`.

Why? Because `*` is a Greedy Quantifier.
By default, the `*` (zero or more) and `+` (one or more) operators are greedy. They will consume as much text as possible while still allowing the rest of the pattern to match. The engine found the first `[`, consumed everything until the very last `]` in the string, and called it a day.

The Solution: Lazy Quantifiers \`.*?\`

To fix this, we need to make the quantifier lazy (also known as non-greedy or reluctant). We do this by appending a question mark `?` to the quantifier.

```regex
[.*?]
```

Open in Sandbox

Now, the engine stops at the first closing bracket it sees. It successfully extracts `[brown]` and then `[lazy]` as two separate matches.

Using Capture Groups

Usually, you don't actually want the brackets themselves; you just want the text inside them. To do this, wrap the lazy quantifier in a Capture Group `()`.

```regex
[(.*?)]
```

In JavaScript, you can access this group easily:
```javascript
const str = "The quick [brown] fox";
const match = str.match(/[(.*?)]/);
console.log(match[1]); // Output: "brown"
```

(Note: If you use the Sandbox link above, you'll see the capture group highlighted in blue under the "Match Details" section!)

Alternative Approach: Negated Character Classes

While lazy quantifiers are great, they can sometimes be slow on massive strings due to how the regex engine evaluates them. A more performant and robust way to match between two characters is using a Negated Character Class.

Instead of saying "match anything until you hit a bracket," you say "match anything that is NOT a bracket."

```regex
[([^]]+)]
```

Here is the breakdown:

  • `[` : Match the literal opening bracket.
  • `(` : Start capture group.
  • `[^` : Start negated character class.
  • `]` : The literal closing bracket.
  • `]` : End character class.
  • `+` : Match one or more of these non-bracket characters.
  • `)` : End capture group.
  • `]` : Match the literal closing bracket.

This approach is significantly faster because the engine doesn't have to constantly look ahead to see if the closing character is coming up. It just consumes everything that isn't a closing bracket.

Test both approaches in the Interactive Regex Sandbox to see which one fits your specific data extraction needs!

Aarav MehtaDeveloper Tools Editor

Aarav writes practical guides for developers and technical users, focusing on browser-based utilities, data formatting, API workflows, security basics, and privacy-first developer tools.

Developer ToolsAPIsJSONRegexBase64UUIDSecurity Tools
View all articles