Regex cheat sheet for beginners

A regular expression is a search pattern: \d{4} finds four digits in a row, ^ and $ pin the match to the start and end, and parentheses capture parts you want to reuse. This cheat sheet lists the syntax you will use most, with patterns for email, phone numbers and dates that were tested on real input. Try every example in the regex tester on this page while you read.

7 min read

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 page

Characters 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 [.-].

PatternMatchesExample
.Any character except a line breakc.t finds cat, cot, c7t
\dA digit 0 to 9\d\d finds 42 in Room 42
\wLetter, digit or underscore (ASCII only)\w+ finds user_01
\sSpace, tab or line breaka\sb finds a b
\D \W \SThe opposite of \d, \w and \s\D finds the x in 4x4
[abc]One of a, b or cgr[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
\bWord 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.

PatternMeaningExample
*0 or more timesab*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 timesa{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|ba or bcat|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.

Step by step

  1. Type the patternWrite the expression in Regular expression, without slashes, or pick one under Common patterns.
  2. Choose the flagsTick g for all matches, i to ignore case, m for line by line anchors and u for letters in any language.
  3. Paste test textAdd text with examples that should and should not match. Matches are highlighted as you type.
  4. Check the groupsRead the Matches table for positions and capture groups.
  5. Preview a replacementTick Replace with, then enter $1, $<name> or $& to see the result before you use it in code.

Frequently asked questions

What does .* mean in regex?

Any character, zero or more times, as many as possible. It is greedy, so .* runs to the end of the line; use .*? to stop at the first possible point.

What is the difference between + and *?

+ needs at least one repetition, * also accepts zero. \d+ requires a digit, \d* matches even an empty string.

How do I match a literal dot, bracket or question mark?

Put a backslash in front: \. \[ \? . Inside square brackets the dot and question mark are already literal, so [.?] works too.

Why does my regex work in one language but not another?

Flavors differ in details: lookbehind support, named group syntax ((?<name>) vs (?P<name>) in Python), \w and Unicode handling. Core syntax like classes, quantifiers and anchors is the same everywhere.

Is the text I test uploaded anywhere?

No. The tester runs in a background worker in your browser, so your logs and data stay on your device. It also works offline once the page has loaded.

Can a regex validate an email address completely?

No. It can reject obvious typos, but only sending an email proves the address exists. Keep the pattern simple and confirm by email.