EasyDeveloper

Regex

Regex Cheat Sheet: Every Metacharacter Explained

Published 2026-08-15 · 8 min read

TL;DR: Regex metacharacters in one place: ^ $ anchors, \d \w \s classes, + * ? quantifiers, ( ) groups and | alternation, plus the i g m s u flags.

This cheat sheet is the condensed reference for the metacharacters you will meet in almost every pattern. Each table pairs a token with its meaning and a compact example, and the paragraphs below the tables add the context the tables leave out. For the full walkthrough, start with the regular expressions guide. For the language reference, the MDN regex page lists every token with examples.

What are the anchors?

TokenMeaningExample
^Start of the string (or line with m flag)^ab matches ab at the start
$End of the string (or line with m flag)ab$ matches ab at the end
\bWord boundary\bcat\b matches cat, not category
\BNot a word boundary\Bcat matches concat

Anchors assert a position instead of consuming a character, which is what makes patterns like ^\d{4}$ mean the entire string must be four digits. Without anchors, a pattern matches anywhere in the input, so search tools match inside longer words unless you bound the ends.

What are the character classes?

TokenMeaningExample
[abc]Any one of a, b or c[aeiou] matches a vowel
[a-z]Any letter in the range[0-9] matches a digit
[^abc]Any character except these[^\s] matches a non-space
\dA digit, same as [0-9]\d{4} matches 2026
\wA word character, [A-Za-z0-9_]\w+ matches username_1
\sWhitespace: space, tab, newline\s+ splits on runs of spaces
.Any character except newlinea.c matches abc, aXc

The uppercase forms are the opposites: \D is a non-digit, \W is a non-word character and \S is non-whitespace. Inside a class, a caret at the start negates the set, and a hyphen between two characters makes a range, so a literal hyphen belongs at the start or end of the class, as in [-a-z].

What are the quantifiers?

TokenMeaningExample
*Zero or moreab* matches a, ab, abb
+One or moreab+ matches ab, not a
?Zero or one, optionalcolou?r matches color and colour
{3}Exactly three\d{3} matches 123
{2,4}Two to four\d{2,4} matches 42 or 4200
{2,}Two or more\d{2,} matches 42, 420, 4200

Quantifiers bind to the single token before them, or to the whole group when the token is a parenthesized group. All the forms are greedy by default, meaning they match as much as possible; appending a question mark, such as +? or *?, makes the match lazy and stops as early as possible.

What are groups and alternation?

TokenMeaningExample
(abc)Capture group, numbered(ab)+ matches abab
(?:abc)Non-capturing group(?:ab)+ matches abab
(?<name>...)Named capture group(?<year>\d{4})
|Alternation, orgray|grey matches both spellings
\1Backreference to group 1(<[^>]+>).*\1

Parentheses do two jobs at once: they group a sub-pattern so quantifiers and alternation apply to it, and they capture the matched text into a numbered slot. The plain group ( ) captures, (?: ) groups without capturing, and named groups give the capture a readable label. A backreference such as \1 repeats whatever the first group matched, which is how you match a pair of identical quotes or tags.

What are the flags?

FlagMeaningExample
gGlobal: return every match/a/g finds all a characters
iCase-insensitive/hello/i matches Hello
mMultiline: ^ and $ match at line breaks/^#/gm matches comment lines
sDot matches newlines/a.b/s matches a\nb
uUnicode moderequired for astral characters

Flags are written after the closing delimiter in JavaScript, as in /ab/gi, or passed as an argument in Python and Java. The unicode flag is the one people forget: without it, patterns that match characters beyond the basic multilingual plane, such as many emoji, can behave unexpectedly or fail.

How do you escape a metacharacter?

To match a metacharacter as a literal, put a backslash in front of it: \. matches a literal dot, \ a literal star, \? a question mark. The metacharacters to remember are . ^ $ + ? ( ) [ ] { } | and the backslash itself. Inside a character class, only \ ] and - usually need care.

\d+\.\d+\.\d+    matches 1.2.3
100\%           matches the text 100%
\[brackets\]     matches [brackets]

How do you combine tokens into a pattern?

Tokens compose left to right. A phone pattern combines classes and quantifiers: three digits, an optional separator, three digits, another optional separator, then four digits. Each piece constrains only its own position, which is why patterns are built by stacking small confident pieces instead of writing one long line. Start from the leftmost constant and add the variable middle.

\d{3}[-.]?\d{3}[-.]?\d{4}    matches 555-123-4567, 555.123.4567

What does a real pattern look like?

A time pattern shows how the pieces fit: two digits for the hour, a colon, two digits for the minute, and an optional AM or PM marker. Writing the whole thing at once feels hard until you split it at the colon, and then each side is a digit class plus a quantifier. The same decomposition works for dates, ids and version numbers: separate the fixed separators from the variable fields, and the pattern writes itself.

\d{2}:\d{2}(?:\s?[AP]M)?    matches 14:30, 09:05 PM

How do you test these patterns?

Paste a pattern and some sample text into the regex tester to see every match highlighted as you type. When a token is not matching the way you expect, check the cheat sheet rows above, or ask the regex escape tool whether you are dealing with a literal that needs escaping.

Frequently Asked Questions

What does the dot match in regex?

The dot matches any single character except a newline by default. In unicode mode with the s flag it matches newlines too. If you need a literal dot, escape it as \. because the unescaped dot is a wildcard.

What is the difference between * and +?

The star matches zero or more of the previous token, so it can match nothing at all. The plus requires one or more. Use * for optional-but-repeatable and + for one-or-more, which is usually what validation wants.

What is a greedy match?

A greedy quantifier consumes as much as possible while still letting the rest of the pattern match. .* is greedy, so it spans to the last occurrence it can. Add a question mark, as in .*?, to make it lazy and stop at the first.

Why is my pattern not matching?

Check for unescaped metacharacters, anchors that are too strict, and case sensitivity. A quick way to narrow it: remove parts until it matches, then add requirements back one at a time with a [regex tester](/tools/regex-tester).

Do I need to escape a slash?

In JavaScript, patterns are often written between slashes, and then the slash inside the pattern must be escaped as \/. In Python and in string-based patterns, the slash has no special meaning and needs no escape.