Symptom: it should match but doesn't
You write what looks like a correct pattern in a regex tester, and either nothing highlights, or it grabs one weird chunk. The two most common cases:
- You use
.*to grab content, but it swallows everything from start to end; - The pattern "looks right" but matches nothing at all.
Here are the frequent traps, explained once.
Trap 1: greedy quantifiers swallow everything
The * in .* is greedy — it matches as much as possible before giving back. With multiple blocks in the text:
<div>A</div><div>B</div>
Using |<div>.*</div>| matches greedily all the way to the last </div>, folding both "A" and "B" into one match.
| Pattern | Meaning | Behavior |
|---|---|---|
| .* | greedy | matches as much as possible |
| .*? | lazy (add ?) | matches as little as possible, stops at first close |
Change it to |<div>.*?</div>| and you get two separate matches for "A" and "B".
Trap 2: special characters not escaped
. + ? * ( ) [ ] { } ^ $ | \ all have special meaning in regex. To match them literally, escape with a backslash:
| You want | Write |
|---|---|
| a literal dot . | \. |
| a literal plus + | \+ |
| a literal paren ( | \( |
This is why "my email regex doesn't match the dot after @".
Trap 3: anchors and multiline mode
^ and $ match the start and end of the whole text by default. For line-by-line matching you must enable multiline mode (the m flag):
^error.*$ # without m: only the first line
^error.*$ # with m flag: every line starting with error
Trap 4: missing flags
| Flag | Effect | Symptom if missing |
|---|---|---|
| g (global) | match all, not just first | only one result returned |
| i (ignore case) | case-insensitive | abc misses ABC |
| m (multiline) | ^ $ per line | anchors fail on multiline text |
How to debug step by step
Open the Regex Tester on ToolVault:
- Paste your test text into the "test text" box;
- Type the pattern; matches highlight live on the right;
- Toggle
g/i/mand watch the behavior change instantly; - Use the "groups" view to confirm each capture group — avoid
.*eating your target.
Everything runs locally; neither pattern nor text is uploaded.
FAQ
Is lazy .*? always better than greedy?
No. Lazy is better for "extract content between two delimiters"; greedy is better when you want "from here to end of line". Pick by need.
Why is a capture group undefined?
Often the parentheses became a character class [()] or were escaped \(, so no capture group formed; or your string has newlines but the s (dotAll) flag is off, so . can't match them.
Can Chinese be used directly outside meta chars?
Yes. Chinese are ordinary characters and match as-is; only the metacharacters listed above need escaping.
Provided by ToolVault. Related tools: JSON Formatter, API Tester, Mock Data Generator. Visit the home page for more developer tools.
Related Tools
Related Articles
API Testing: How to Send a Token and Fix CORS Errors
How to add an Authorization token when testing APIs online, and what to do about CORS / 405 / timeout errors? A step-by-step troubleshooting guide with our API tester.
Mock Data Generator Complete Guide: Generate Test Data Fast
Learn how to use a mock data generator to quickly create various types of test data, boosting frontend development and testing efficiency
JSON to TypeScript: Complete Guide to Auto-Generating Type Definitions
Step-by-step tutorial on how to quickly convert JSON data to TypeScript interfaces and type definitions, boosting development efficiency and code quality