14 min read

Regex Cheat Sheet with Live Examples (2026)

A complete, bookmark-worthy regex reference with tested examples for every pattern. Copy the patterns, test them live in our free regex tester, and stop Googling the same syntax.

Basic Syntax: The Building Blocks

Every regex pattern is built from a small set of fundamental syntax elements. If you know these, you can read any regular expression. Test each pattern live in the QTool Regex Tester as you read.

Pattern Meaning Example Matches
. Any character (except newline) h.t "hat", "hot", "h t"
\ Escape special character \. Literal "."
| OR (alternation) cat|dog "cat" or "dog"
[] Character set [aeiou] Any vowel
[^] Negated character set [^0-9] Any non-digit
- Range (inside []) [a-z] Any lowercase letter

Character Classes

Character classes are shortcuts for common character sets. They save typing and make patterns more readable.

Pattern Equivalent Meaning
\d [0-9] Any digit
\D [^0-9] Any non-digit
\w [a-zA-Z0-9_] Word character (letter, digit, underscore)
\W [^a-zA-Z0-9_] Non-word character
\s [ \t\n\r\f\v] Whitespace (space, tab, newline)
\S [^ \t\n\r\f\v] Non-whitespace
// Extract all numbers from a string
const text = "Order #4521 has 3 items totaling $149.99";
const numbers = text.match(/\d+\.?\d*/g);
// Result: ["4521", "3", "149.99"]

// Extract all words
const words = text.match(/\w+/g);
// Result: ["Order", "4521", "has", "3", "items", "totaling", "149", "99"]

Anchors and Boundaries

Anchors do not match characters. They match positions in the string. This is a subtle but critical distinction.

Pattern Meaning Example Matches in "the cat sat"
^ Start of string (or line with m flag) ^the "the" at the start
$ End of string (or line with m flag) sat$ "sat" at the end
\b Word boundary \bcat\b "cat" (not "category")
\B Non-word boundary \Bcat\B "cat" in "concatenate"
Common Gotcha

^ and $ match the start/end of the entire string by default. With the m (multiline) flag, they match the start/end of each line. This distinction trips up developers regularly when processing multi-line text. Test with the multiline flag toggled on and off in the Regex Tester to see the difference.

Quantifiers: How Many Times

Pattern Meaning Greedy Example Lazy Version
* 0 or more a* matches "", "a", "aaa" *?
+ 1 or more a+ matches "a", "aaa" +?
? 0 or 1 (optional) colou?r matches "color", "colour" ??
{n} Exactly n times \d{4} matches "2026" N/A
{n,} n or more times \d{2,} matches "42", "123" {n,}?
{n,m} Between n and m times \d{2,4} matches "42", "123", "1234" {n,m}?

Greedy vs. lazy: why it matters

By default, quantifiers are greedy: they match as much as possible. Adding ? after a quantifier makes it lazy: it matches as little as possible.

// Greedy: matches the LONGEST possible
"<b>hello</b> and <b>world</b>".match(/<b>(.*)<\/b>/);
// Capture group 1: "hello</b> and <b>world"

// Lazy: matches the SHORTEST possible
"<b>hello</b> and <b>world</b>".match(/<b>(.*?)<\/b>/);
// Capture group 1: "hello"

// With global flag, lazy finds both matches
"<b>hello</b> and <b>world</b>".match(/<b>(.*?)<\/b>/g);
// Result: ["<b>hello</b>", "<b>world</b>"]

Groups and Capturing

Pattern Meaning Example
(pattern) Capturing group (\d{4})-(\d{2})-(\d{2}) captures year, month, day
(?:pattern) Non-capturing group (?:http|https):// groups without capturing
(?<name>pattern) Named capturing group (?<year>\d{4}) captures as "year"
\1 Backreference to group 1 (\w+)\s+\1 matches repeated words
\k<name> Named backreference (?<word>\w+)\s+\k<word>
// Parse a date with named groups
const dateStr = "2026-02-13";
const match = dateStr.match(/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/);
console.log(match.groups.year);   // "2026"
console.log(match.groups.month);  // "02"
console.log(match.groups.day);    // "13"

// Find repeated words (common typo detection)
const text = "the the quick brown fox fox";
const dupes = text.match(/\b(\w+)\s+\1\b/g);
// Result: ["the the", "fox fox"]

Test capturing groups visually using the QTool Regex Tester -- it highlights each capture group in a different color and displays group values separately.

Lookahead and Lookbehind

Lookaround assertions check for patterns without including them in the match. They are zero-width: they assert that something exists but do not consume characters.

Pattern Name Meaning Example
(?=pattern) Positive lookahead Followed by pattern \d+(?= dollars) matches "100" in "100 dollars"
(?!pattern) Negative lookahead NOT followed by pattern \d+(?! dollars) matches "200" in "200 euros"
(?<=pattern) Positive lookbehind Preceded by pattern (?<=\$)\d+ matches "50" in "$50"
(?<!pattern) Negative lookbehind NOT preceded by pattern (?<!\$)\d+ matches "50" in "50 items"
// Password validation: at least 1 uppercase, 1 lowercase, 1 digit, 8+ chars
const passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/;
passwordRegex.test("Secure123");  // true
passwordRegex.test("weak");       // false

// Extract prices without the $ symbol
const prices = "free.99 and $149.00".match(/(?<=\$)\d+\.?\d*/g);
// Result: ["29.99", "149.00"]

// Match "foo" only when NOT preceded by "bar"
/(?<!bar)foo/.test("foobar");    // true (foo is not preceded by "bar")
/(?<!bar)foo/.test("barfoo");    // false (foo IS preceded by "bar")

Regex Flags

Flag Name Effect
g Global Find all matches, not just the first
i Case-insensitive /hello/i matches "Hello", "HELLO"
m Multiline ^ and $ match line starts/ends
s DotAll . also matches newline characters
u Unicode Enables full Unicode matching, \p{} categories
d Indices Generates indices for matched substrings
v UnicodeSets Extended Unicode property classes (ES2024+)
// Unicode flag: match accented characters, CJK, emojis
/\p{Letter}/u.test("e");    // true (e is a letter)
/\p{Letter}/u.test("4");    // false
/\p{Emoji}/u.test("@");     // false

// DotAll flag: . matches newlines
"line1\nline2".match(/.+/s);   // ["line1\nline2"]
"line1\nline2".match(/.+/);    // ["line1"]

Real-World Patterns You Can Copy

These are tested, production-ready patterns for common validation and extraction tasks. Copy them directly or paste them into the Regex Tester to experiment.

Email (practical validation)

^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$

Covers 99.9% of real email addresses. The RFC 5322-compliant regex is thousands of characters long and unnecessary for practical validation.

URL

https?:\/\/[^\s/$.?#].[^\s]*

Matches HTTP and HTTPS URLs. For stricter validation, use the URL constructor in JavaScript: new URL(str) throws on invalid URLs.

IPv4 address

^(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$

Validates each octet is 0-255. Rejects "999.999.999.999" and "1.2.3.999".

Phone number (international)

^\+?[1-9]\d{6,14}$

Matches E.164 format. For display formatting, use a library like libphonenumber.

Date (YYYY-MM-DD)

^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$

Validates format and month/day ranges. Does not validate actual calendar dates (Feb 30 passes). For full validation, parse with new Date() and check isNaN().

Hex color code

^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$

Matches #FFF, #FF00FF, and #FF00FF80 (with alpha). Use the Color Converter to translate between hex, RGB, and HSL formats.

Slug (URL-friendly string)

^[a-z0-9]+(?:-[a-z0-9]+)*$

Matches "hello-world", "my-blog-post-123". Rejects leading/trailing hyphens and consecutive hyphens. Generate slugs from titles with the Slug Generator.

HTML tag extraction

<(\w+)([^>]*)>(.*?)<\/\1>

Captures tag name, attributes, and content. Works for simple cases but cannot handle nested tags of the same type. For HTML parsing, always use a proper parser (DOMParser, cheerio, etc.).

Test These Patterns Live

Paste any pattern from this cheat sheet into the QTool Regex Tester. See matches highlighted in real time, inspect capture groups, and toggle flags.

Open Regex Tester

JavaScript Regex Methods Quick Reference

const str = "Hello World 123";
const re = /(\w+)\s(\w+)/;

// test() — returns boolean
re.test(str);                    // true

// match() — returns matches array
str.match(/\d+/g);              // ["123"]

// matchAll() — returns iterator of all matches with groups
[...str.matchAll(/(\w+)/g)];    // Full match objects with indices

// replace() — string replacement
str.replace(/World/, "Regex");  // "Hello Regex 123"

// replace() with capture groups
"2026-02-13".replace(
  /(\d{4})-(\d{2})-(\d{2})/,
  "$2/$3/$1"
);                               // "02/13/2026"

// replaceAll() — replace all occurrences
"a-b-c".replaceAll("-", "_");   // "a_b_c"

// split() — split by pattern
"one, two , three".split(/\s*,\s*/);  // ["one", "two", "three"]

// search() — returns index of first match
str.search(/\d/);               // 12

// exec() — returns match object (stateful with g flag)
re.exec(str);                   // ["Hello World", "Hello", "World"]

For find-and-replace across text files and code, the Diff Checker helps you verify that your regex replacements produced the expected output. The Regex Builder helps you construct patterns step by step if you prefer a visual approach.

8 Common Regex Mistakes

  1. Forgetting to escape special characters. Characters like ., (, ), [, {, *, +, ?, ^, $, |, \ have special meaning. To match them literally, escape with \.
  2. Using .* when you mean .*?. Greedy matching grabs everything. If you are matching between delimiters (quotes, tags, brackets), lazy matching (.*?) is almost always what you want.
  3. Forgetting the g flag. Without g, match() returns only the first match. With g, it returns all matches. This is the most common "why does it only find one" bug.
  4. Anchoring incorrectly. /hello/ matches "hello" anywhere in the string. /^hello$/ matches only strings that are exactly "hello". When validating input, you almost always want both anchors.
  5. Not accounting for newlines. By default, . does not match \n. Use the s (dotAll) flag if you need . to match everything including newlines.
  6. Catastrophic backtracking. Patterns like (a+)+$ can cause exponential backtracking on certain inputs, freezing your application. Avoid nested quantifiers on the same character set. Test with long inputs in the Regex Tester to catch performance issues early.
  7. Using regex to parse HTML. Regular expressions cannot reliably parse nested structures. Use DOMParser, cheerio, or similar tools for HTML parsing. Regex is fine for extracting simple patterns from HTML, but not for structural parsing.
  8. Double-escaping in string constructors. In new RegExp("\\d+"), you need \\d (double backslash) because the string literal consumes the first backslash. With regex literals (/\d+/), single backslash works. This is a frequent source of "pattern does not match" bugs.
// WRONG: catastrophic backtracking
const bad = /^(a+)+$/;
bad.test("aaaaaaaaaaaaaaaaaaaaaaaa!");  // Hangs!

// FIXED: remove nested quantifier
const good = /^a+$/;
good.test("aaaaaaaaaaaaaaaaaaaaaaaa!");  // false, instantly

// WRONG: double-escaping in RegExp constructor
new RegExp("\d+");       // Same as /d+/ — matches "d", not digits
new RegExp("\\d+");      // Same as /\d+/ — matches digits correctly
Best Practice

Always use regex literals (/pattern/flags) when the pattern is static. Only use new RegExp() when the pattern is dynamically constructed from variables. This avoids double-escaping bugs and is slightly faster because the regex is compiled at parse time.

Frequently Asked Questions

What is the difference between .* and .*? in regex?

.* is a greedy quantifier -- it matches as many characters as possible. .*? is a lazy (non-greedy) quantifier -- it matches as few characters as possible. For example, given the string <b>hello</b><b>world</b>, the pattern <b>(.*)</b> greedily captures "hello</b><b>world", while <b>(.*?)</b> lazily captures just "hello". Use lazy quantifiers when you want the shortest match between delimiters.

How do I match an email address with regex?

A practical email regex for input validation is: ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$. This matches most real-world email addresses. The RFC 5322-compliant regex is thousands of characters long and rarely needed. For production validation, use this simple pattern for client-side feedback and verify with an actual email delivery attempt server-side.

What is a lookahead in regex and when should I use it?

A lookahead is a zero-width assertion that checks if a pattern exists ahead of the current position without consuming characters. Positive lookahead (?=pattern) asserts that the pattern follows. Negative lookahead (?!pattern) asserts that it does NOT follow. Common use cases include password validation (checking for required character types), matching words only in specific contexts, and complex find-and-replace operations. Test lookaheads interactively in the QTool Regex Tester.

What is the best free regex tester online in 2026?

The QTool Regex Tester is one of the best free options. It provides real-time match highlighting, group extraction, flag toggles, and match count in a clean, ad-free interface running entirely in your browser. For building regex visually, the QTool Regex Builder provides a step-by-step interface that constructs patterns from components. Both are part of QTool's collection of 269 free developer tools.

How do I make regex case-insensitive?

Use the i flag. In JavaScript: /pattern/i or new RegExp('pattern', 'i'). In Python: re.compile('pattern', re.IGNORECASE) or use the inline flag (?i) at the start of the pattern. The i flag makes all alphabetic matches ignore case, so /hello/i matches "hello", "Hello", "HELLO", and any other case variation.

Explore QTool for free

Browse 269 indexed tool pages with no QTool account required, and inspect the source on GitHub.

View on IT-Tools →
NT

Christian Bucher

We build free, privacy-first developer tools. 269 tools for regex, JSON, CSS, images, and more -- all browser-based, no signup required.

Related Tools

CSS Box Shadow Generator · Emoji Picker & Search · Free Regex Playground

Related Tools

Free Regex Pattern Generator · Free JSON to YAML Converter · Free API Mock Server

Built by Miguel

Need a custom tool or website?

From . Delivered in 24-48h. You own the code.

View Services →