The basics in one minute
Most characters match themselves: cat finds the letters c, a, t in that order, anywhere in the text, including inside concat. A few characters have special meaning: . ^ $ * + ? ( ) [ ] { } | and the backslash. To match one of them literally, put a backslash in front: \. matches a real dot and \$ a dollar sign.
The examples here use JavaScript syntax, which is what browsers, Node.js and the tester on this page run. Python, PHP (PCRE), Java and .NET share almost all of it; the differences are mostly in lookbehind, named group syntax and a few escapes. Type a pattern into Regular expression without the surrounding slashes, paste text into Test text, and every match is highlighted.
Try it here: Regex Tester
Open the full tool pageCharacters and classes
A character class matches one character from a set. [aeiou] matches one vowel, [a-z] one lowercase ASCII letter, [^0-9] anything that is not a digit. Inside square brackets most special characters lose their meaning, so [.?] matches a dot or a question mark. Put a hyphen first or last if you want a literal hyphen: [-.] or [.-].
| Pattern | Matches | Example |
|---|---|---|
| . | Any character except a line break | c.t finds cat, cot, c7t |
| \d | A digit 0 to 9 | \d\d finds 42 in Room 42 |
| \w | Letter, digit or underscore (ASCII only) | \w+ finds user_01 |
| \s | Space, tab or line break | a\sb finds a b |
| \D \W \S | The opposite of \d, \w and \s | \D finds the x in 4x4 |
| [abc] | One of a, b or c | gr[ae]y finds gray and grey |
| [^abc] | Any character except a, b or c | [^,]+ finds text between commas |
| \p{L} | Any letter in any language (u flag) | \p{L}+ finds café and Straße |
| \b | Word boundary (no character) | \bcat\b finds cat but not concat |
Quantifiers, anchors and groups
Quantifiers say how many times the thing before them repeats. Anchors match a position, not a character. Groups bundle parts of a pattern together, capture what they matched and let you choose between alternatives.
| Pattern | Meaning | Example |
|---|---|---|
| * | 0 or more times | ab*c finds ac, abc, abbc |
| + | 1 or more times | \d+ finds 7 and 2026 |
| ? | 0 or 1 time (optional) | colou?r finds color and colour |
| {3} | Exactly 3 times | \d{3} finds 555 |
| {2,4} | Between 2 and 4 times | \d{2,4} finds 12, 123, 1234 |
| {2,} | 2 or more times | a{2,} finds aa and aaaa |
| *? +? ?? | Lazy: as few as possible | <.+?> finds <b> and </b> separately |
| ^ | Start of text (or line with m flag) | ^Error finds Error only at the start |
| $ | End of text (or line with m flag) | \.pdf$ finds names ending in .pdf |
| (abc) | Capture group, reuse as $1 | (\d{4})-(\d{2}) captures year and month |
| (?:abc) | Group without capturing | (?:ab)+ finds ababab |
| (?<year>\d{4}) | Named group, reuse as $<year> | Shows as year in the groups table |
| a|b | a or b | cat|dog finds either word |
| (?=x) (?!x) | Followed by x, not followed by x | \d+(?=px) finds 16 in 16px |
| (?<=x) (?<!x) | Preceded by x, not preceded by x | (?<=\$)\d+ finds 25 in $25 |
Flags
Flags change how the whole pattern behaves. In the tester they are checkboxes next to the pattern; in JavaScript code they follow the closing slash, as in /cat/gi.
- g (global): find all matches instead of stopping at the first. Needed for replace all.
- i (ignore case): Cat, CAT and cat all match cat.
- m (multiline): ^ and $ match at the start and end of every line, not only the whole text. Use it for logs and lists.
- s (dotAll): the dot also matches line breaks, so .* can span lines.
- u (Unicode): enables \p{L} and other property escapes, treats emoji and other characters outside the basic plane as one character, and rejects unknown escapes.
- y (sticky): the match must start exactly where the previous one ended. Mostly used when writing tokenizers.
Tested patterns for email, phone and dates
These patterns were checked against valid and invalid samples. Add ^ at the start and $ at the end when you validate a whole input field, and leave them out when you search inside longer text.
Email: [\w.+-]+@[\w-]+(\.[\w-]+)+ matches ana.lopez+news@mail.example.com and a@b.co, and rejects me@localhost because it requires a dot in the domain. It is the Email pattern under Common patterns in the tester. No regex can confirm that an address really exists; for that, send a confirmation email. The official address grammar (RFC 5322) allows forms that a practical pattern should reject anyway.
Phone, international E.164 format: \+[1-9]\d{6,14} matches +14155552671 and +34612345678, the format used by SMS and calling APIs (a plus, a country code and at most 15 digits in total). For US numbers written by people, \(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4} matches (555) 123-4567, 555.123.4567 and 5551234567. It also accepts an unbalanced (555 123-4567, so normalize numbers by removing everything except digits before you store them. To find mixed international numbers in text, such as +44 20 7946 0958 or +1 (555) 123-4567, use the Phone pattern under Common patterns in the tester.
Date, ISO format YYYY-MM-DD: \d{4}-\d{2}-\d{2} finds anything shaped like a date. A stricter version, (19|20)\d{2}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]), rejects month 13 and day 00 but still accepts 2026-02-31. Regex checks the shape; check whether the day exists with your language's date functions.
Reformat dates with replace: search for (\d{4})-(\d{2})-(\d{2}), tick Replace with, type $3.$2.$1 into the box next to it, and 2026-10-26 becomes 26.10.2026.
Common mistakes and how to fix them
- Forgetting to escape the dot: example.com also matches exampleXcom. Write example\.com.
- Greedy matching: <.+> on <b>bold</b> matches the whole string. Use the lazy <.+?> or a negated class <[^>]+>.
- Missing anchors in validation: \d{5} accepts abc12345xyz because it finds five digits inside. Use ^\d{5}$.
- Expecting \w to match accented letters: without the u flag it covers only A-Z, a-z, 0-9 and _. Use \p{L} with the u flag for names in any language.
- Forgetting the g flag: replace changes only the first match, and the tester shows only one.
- Nested quantifiers like (a+)+ or (\w+\s?)+$: on some inputs they take exponential time, called catastrophic backtracking. The tester stops a pattern after 1.5 seconds and tells you; rewrite it so each part can match in only one way.
- Parsing HTML or JSON with regex: fine for a quick search, unreliable for real parsing. Use a parser for anything nested.
How to build a pattern step by step
Start with a literal piece of the text you want, for example 2026-10-26, and confirm it matches. Then replace parts with classes one by one: \d{4}-10-26, then \d{4}-\d{2}-\d{2}. After each change look at what else is highlighted in the test text, and add a few lines that should not match. A good test text contains both the cases you want and the near misses.
Open the Matches table to see the position and every capture group of each match. If a group shows the wrong part, move the parentheses. When the pattern works, copy it into your code as it is: JavaScript and the tester use the same engine, so the result will be identical.