Regex Cheat Sheet & Tester

Share:

Search 80+ ready-to-copy regex patterns and test your own regex against sample text — all in your browser.

RT-DEV-065 · Developer Tools
Your browser is too old for this tool’s interactive features. Please update to Safari 13.1, Chrome or Edge 80, Firefox 74 or newer.

Regex Cheat Sheet & Tester

Pattern library

Live tester

📅 Research current as of 14 Sep 2026 · Sources: ECMA-262 (ECMAScript Language Specification) §22.2 for the pattern grammar, the CharacterClassEscape definitions of \d and \w, the ASCII word-character rule behind \b, the backtracking match semantics and the flag set; the tester runs the browser's own RegExp, so the spec is also the implementation
Standards, published formulas, and reference data are revised over time — check against a current authoritative source before relying on these figures.
Advertisement
After results · AD-W1 Responsive · Post-tool — peak engagement

How to use the regex cheat sheet

Search or filter the library

Type a keyword in the search box (e.g. "email", "URL", "Singapore postal") or click a category pill to narrow the list. Every pattern shows a one-line example of what it matches.

Copy a pattern

Click Copy to grab the pattern as text, or click Use to push it straight into the tester on the right with the flags already set.

Paste your sample text

Drop the text you want to search into the "Test against" box. The tool runs your regex against the text on every keystroke and highlights every match in yellow.

Adjust flags as needed

The box goes straight to the browser's RegExp constructor, so it takes the ECMAScript flag set: d (indices), g (global), i (ignore case), m (multiline anchors), s (dot matches line terminators), u (unicode), v (unicode sets) and y (sticky). u and v cannot be combined — that is a syntax error, and it will show as one. The match count updates live and an invalid pattern shows a red error line. Note the field is capped at six characters, which is enough for any sane combination and short of all eight.

Advertisement
After how-to · AD-W2 Responsive

Regular expressions — the developer's swiss-army knife

Regular expressions ("regex") are tiny domain-specific languages for describing patterns in text. A pattern like \b\d{3}-\d{4}\b describes "three digits, a hyphen, four digits, as a whole word." Once written, regex engines built into PHP, JavaScript, Python, Java, Ruby, Go, Rust, and every modern command-line tool can find, validate, split, or replace text matching that pattern at high speed. For developers, regex is the difference between writing thirty lines of string-walking code and writing one line that does the same job, faster.

Where regex shines

Anywhere you would otherwise hand-write a parser for a small, flat format. Validating that an email looks roughly right, pulling every URL out of a markdown file, splitting a phone number into country code and local digits, finding UUIDs in a log, redacting NRICs before a log leaves the building — all one- to three-line regex problems. The library above holds 82 patterns so the common ones do not have to be reinvented each time.

Where regex stops being the right tool

The classic example is parsing HTML or JSON with regex. These languages are nested, and regex (with the textbook computer-science definition of "regular") cannot match arbitrarily nested structures. Real-world engines like PCRE add features that bend the rule — backreferences, recursive subpatterns — but the maintainability cost is enormous. If you find yourself writing more than 60 characters of regex for a single pattern, or nesting capture groups three levels deep, stop and use a proper parser. DOMDocument in PHP, BeautifulSoup in Python, cheerio in Node — they exist for a reason.

ASEAN-specific patterns

Most published regex collections assume US or UK formats, so the library carries a regional set: Singapore NRIC, postal code, phone and GST registration number; Malaysian IC; Indonesian KTP and phone; Philippine mobile; Thai citizen ID.

Every one of them checks shape, and shape is weaker than it looks. A Singapore NRIC ends in a check letter derived arithmetically from the digits, so [STFGM]\d{7}[A-Z] accepts twenty-five wrong letters for every right one. A Singapore postal code is six digits, but the first two are a sector code and not all pairs are allocated, so \b\d{6}\b also matches any other six-digit run in your text. An Indonesian KTP number encodes province, regency, district, date of birth and sex; \b\d{16}\b knows none of that. A credit-card number has a Luhn checksum the loose pattern does not compute. Use these to find candidates — in a redaction pass, an extraction, a first-pass form hint — and validate properly afterwards. A regex that reports a malformed ID as valid is worse than no check, because it ends the enquiry.

Three ECMAScript rules worth knowing before you debug

\d is exactly ten characters, and u does not change that. ECMA-262 defines it flatly: CharacterClassEscape :: d — Return the ten-element CharSet containing the characters 0, 1, 2, 3, 4, 5, 6, 7, 8, and 9. There is no unicode-aware variant. /\d/u.test("٣") is false for the Arabic-Indic three, with or without the flag. This differs from Python 3 and .NET, where \d is unicode-aware by default — so a pattern ported between them does not mean the same thing.

\w and \b are ASCII, which is why accented text breaks them. The spec builds both from the ASCII word characters, adding others only in the narrow case of the unicode and ignore-case flags together. In practice: /\bcafé\b/ does not match café, and "café".match(/\w+/g) returns ["caf"] — it stops at the é. For real-world text use a Unicode property escape such as \p{L} with the u flag.

A global regex carries state between calls. With g (or y) set, the object remembers a lastIndex and the next .test() or .exec() resumes from there — so the same regex object tested twice against the same string alternates true and false. It is the reason a shared module-level const RE = /…/g produces bugs that only appear on the second call. Either build the regex where you use it, or reset lastIndex yourself.

When regex is the wrong tool

Three signals to stop and reach for a parser: you are matching balanced delimiters at arbitrary depth, you are pulling structured data out of HTML or JSON, or the pattern no longer fits on a screen. Regex is excellent at flat patterns and fragile at grammars — and the fragility is not only about correctness, as the backtracking facts below show.

What the ECMAScript spec actually says about \d, \b and backtracking

01

Regular expressions were introduced by mathematician Stephen Kleene in 1951 as a way to formalise pattern matching in automata theory — three decades before they became a programming staple.

02

The Unix tool grep was written by Ken Thompson in 1973 and got its name from the ed editor command g/re/p — "globally search a regular expression and print." It still ships with every Unix-like OS today.

03

Backtracking is in the standard, not just the engine. ECMA-262 defines matching with continuations and notes that due to backtracking, many MatchStates may be in use at any time during the matching process. So (a+)+b against a long run of as followed by X is exponential by specification — no conforming engine optimises it away.

04

No email regex can be both correct and useful. RFC 5322's addr-spec admits quoted local parts ("very.unusual"@example.com), comments, and domain literals, so a pattern that accepts everything valid rejects almost nothing. The one in this library is a deliberate approximation; the only real validation is sending to the address.

05

The Singapore NRIC checksum is computed by multiplying each digit by a fixed weight, summing, mod 11, then mapping to a letter — making a "syntactically valid" NRIC regex possible but a "really valid" check requires the math too.

06

\d is ten characters, always. ECMA-262: Return the ten-element CharSet containing the characters 0, 1, 2, 3, 4, 5, 6, 7, 8, and 9. The u flag does not widen it — /\d/u.test("٣") is false. Python 3 and .NET disagree, which is why ported patterns change meaning.

07

\w and \b stop at ASCII. The spec builds both from the ASCII word characters, so /\bcafé\b/ does not match café and "café".match(/\w+/g) returns ["caf"]. For text in any other script, use \p{L} with the u flag.

08

Cloudflare suffered a major outage in 2019 caused by a single regex that took exponential time on certain inputs. The post-mortem became required reading for backend engineers everywhere.

09

A g regex remembers where it stopped. With g or y set, the object keeps a lastIndex and the next call resumes from it — so testing one regex object twice against the same string returns true, then false. A module-level const RE = /…/g is the classic way to ship a bug that only appears on the second call.

10

Two characters that print the same are two characters. The Greek question mark ; (U+037E) and the semicolon ; (U+003B) are indistinguishable in most fonts, and /;/ matches only the second. The same trap catches full-width digits and the several dashes people paste into date fields — a pattern operates on code points, never on shapes.

Frequently asked questions

You're missing the g (global) flag. Without it, the engine returns after the first match. Add g to the flags box on the right side of the pattern input.
In JavaScript, nothing at all, in every flag combination. ECMA-262 defines \d as the ten-element CharSet containing the characters 0, 1, 2, 3, 4, 5, 6, 7, 8, and 9, and the u flag does not widen it — /\d/u.test('٣') is false. The difference appears when you port the pattern: Python 3 and .NET make \d unicode-aware by default, so the same three characters match a different set of digits there. Write [0-9] when you mean ASCII digits and want the pattern to survive the move.
Use regex for flat, well-defined patterns: emails, phone numbers, IDs, dates, simple log lines. Use a real parser for nested structures: HTML, JSON, XML, source code. If your regex exceeds about 60 characters or nests groups three levels deep, switch to a parser.
No, and the gap is wider than it sounds. [STFGM]\d{7}[A-Z] accepts any trailing letter, so twenty-five of every twenty-six NRICs it passes carry the wrong check letter. \b\d{6}\b for a Singapore postal code matches any six-digit run in the text and knows nothing about which sector codes are allocated. The credit-card pattern computes no Luhn checksum. Treat these as finders — for redaction, extraction or a first-pass hint — and validate arithmetically before you act on the result.
Also called the "dotall" flag. By default, the . metacharacter matches any character except a newline. With s enabled, . matches newlines too — useful for matching across multiple lines.
It depends on the m (multi-line) flag. Without m, ^ matches only the start of the entire input and $ the end. With m, both match at every line boundary. Same for $.
In the strict sense, no — that requires a context-free grammar. Real-world engines like PCRE add recursive subpatterns ((?R)) that handle limited nesting, but the patterns become unreadable. For nested structures, write a proper parser.
One where a nested quantifier lets the engine split the same input many ways: (a+)+b against a run of as with no b forces it to try every partition before failing, which is exponential in the length of the run. This is specified behaviour rather than an engine weakness — ECMA-262 defines matching in terms of backtracking through MatchStates, so no conforming engine can skip the work. Avoid quantifying a group that is itself quantified; where an engine offers them, atomic groups or possessive quantifiers cut the search. If a pattern runs against text you did not write, assume someone will eventually send the pathological input on purpose.
Yes. The tool uses the browser's built-in RegExp object. Your pattern and test text never leave the page; nothing is sent to any server. You can verify this by opening the browser network tab — no requests fire while you type.
The syntax used here is portable across PCRE (PHP), Python re, java.util.regex and JavaScript — character classes, quantifiers, non-capturing groups, anchors. What is not portable is what the shorthands mean. \d is ASCII-only in JavaScript and unicode-aware by default in Python 3 and .NET; \w and \b follow the same split. A pattern that reads identically in two languages can therefore match different text in each, and the ID patterns are where that bites, because a unicode-aware \d will accept Arabic-Indic digits in a field that should only take ASCII ones.

Method & sources

How it computes

A library of 82 named patterns grouped by category, plus a live tester that constructs the browser's own RegExp from the pattern and flag string and re-runs it on every keystroke. Because the tester is ECMAScript's RegExp, the ECMAScript specification is both the reference and the implementation: \d is exactly [0-9], \w and \b are ASCII-based, and matching is defined in terms of backtracking. Nothing is sent to a server.

What this tool implements

  • ECMA-262 §22.2 is the authority for everything the tester does, because the tester is the engine. The page quotes the spec rather than describing engine behaviour: 'CharacterClassEscape :: d — Return the ten-element CharSet containing the characters 0, 1, 2, 3, 4, 5, 6, 7, 8, and 9.'
  • \w and \b are built from 'the ASCII word characters', widened only when the unicode and ignore-case flags are both set. The page gives the two consequences a reader will actually hit: /\bcafé\b/ does not match café, and "café".match(/\w+/g) returns ["caf"].
  • Catastrophic backtracking is presented as specified behaviour, not an engine defect: ECMA-262 defines matching with MatcherContinuations and states that 'due to backtracking, many MatchStates may be in use at any time during the matching process'.
  • The flag box is documented against the full ECMAScript set — d, g, i, m, s, u, v, y — including that u and v are mutually exclusive, and that the input is capped at six characters.
  • lastIndex statefulness on g and y regexes is stated, because it is the JavaScript-specific behaviour a tester cannot show you.
  • Every regional ID pattern is labelled format-only, with the specific thing each one misses: the NRIC check letter, unallocated Singapore postal sector codes, the structure encoded in an Indonesian KTP, the Luhn checksum on a card number.

Sources

  • ECMA-262, ECMAScript Language Specification, §22.2 RegExp (Regular Expression) Objects — the Pattern grammar, CharacterClassEscape definitions for d, D, w, W, the WordCharacters abstract operation, the MatchState/MatcherContinuation backtracking semantics, and the flag set: https://tc39.es/ecma262/multipage/text-processing.html
  • RFC 5322, Internet Message Format, §3.4.1 Addr-Spec Specification — the grammar admitting quoted local parts and domain literals that makes a fully conformant email regex useless in practice: https://www.rfc-editor.org/rfc/rfc5322
  • Kleene SC. Representation of Events in Nerve Nets and Finite Automata. RAND Research Memorandum RM-704, 1951; published in Shannon CE, McCarthy J (eds), Automata Studies, Princeton University Press, 1956:3-41.
  • Cloudflare. Details of the Cloudflare outage on July 2, 2019 — the post-mortem of an outage caused by a single WAF regular expression with catastrophic backtracking: https://blog.cloudflare.com/details-of-the-cloudflare-outage-on-j…
  • MDN Web Docs, Regular expression syntax — used only for the engine-specific notes (lastIndex behaviour on global regexes, flag availability) that ECMA-262 states in specification language: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference…
  • Infocomm Media Development Authority. National Numbering Plan — Level '3' numbers are allocated to IP telephony; the Singapore phone pattern was widened from [896] to [3689] on 2026-09-14 to match. https://www.imda.gov.sg/regulations-and-licensing-listing/numberi…

What can make this go out of date

  • None at runtime. The pattern library is a literal array in the page's own JavaScript and the tester uses the browser's RegExp; nothing is fetched and nothing you type is transmitted.
  • The regional ID patterns encode national numbering and identity formats that change by regulation — a new Singapore phone prefix or a new NRIC series letter would make a pattern silently incomplete rather than obviously wrong.

Abridged — the full review record for this tool runs longer than the list above.

Advertisement
Pre-footer · AD-W3 728 × 90