Regex Cheat Sheet — Every Token With Examples
Every regular expression token with a working example, support in JavaScript, PCRE/PHP, Python, Go, Java and .NET, and a Try it link that opens the regex tester pre-filled.
Last verified: 2026-10-18 against ECMAScript 2025 (MDN), PCRE2 10.45, Python 3.14 re, Go 1.27 regexp/syntax, Java 25 Pattern and the .NET regex reference. Sources: MDN regular expressions, PCRE2 pattern syntax, Python re, Go regexp/syntax, Java Pattern, .NET regex quick reference.
Characters and escapes
Most characters match themselves. These twelve have a special meaning and need a backslash to be matched literally: \ ^ $ . | ? * + ( ) [ { (and ] } in some positions).
.Any characterAny single character except a line break. Add the s (dotAll) flag to include line breaks.
/h.t/g
on “hat hot h t hit h↵t”
matches “hat” “hot” “h t” “hit”- Python re: Excludes only \n; JavaScript also excludes \r, \u2028 and \u2029.
- Go RE2: Excludes only \n.
\. \$ \(Escape a metacharacterA backslash makes the next special character literal: \. is a real dot, \$ a dollar sign.
/\$\d+\.\d{2}/g
on “Total $45.00, tax $3.15, tip 5”
matches “$45.00” “$3.15”\t \n \rTab, newline, carriage returnControl characters by name. Windows line endings are \r\n; \r?\n matches both styles.
/\w+\t\w+/g
on “name⇥age↵ana⇥31”
matches “name⇥age” “ana⇥31”\xhhCharacter by hex codeExactly two hex digits: \x41 is A, \x20 a space.
/\x41/g
on “A b A”
matches “A” “A”\uhhhhCharacter by Unicode code unitFour hex digits for a character in the Basic Multilingual Plane: \u00e9 is é.
/\u00e9/g
on “café résumé”
matches “é” “é” “é”- PCRE / PHP: Use \x{e9}.
- Go RE2: Use \x{e9}.
\u{1F600}Any code point (astral too)Braced code point, needed for emoji and other characters above U+FFFF. JavaScript requires the u or v flag.
/\u{1F600}/gu
on “Hi 😀 there 😀”
matches “😀” “😀”- PCRE / PHP: Write \x{1F600} (PHP needs the u modifier).
- Python re: Write \U0001F600 (eight hex digits).
- Go RE2: Write \x{1F600}.
- Java: Write \x{1F600}.
- .NET: Only \uhhhh; an emoji is two UTF-16 code units, e.g. 😀.
Character classes
A class matches exactly one character from a set. Inside [ ], most metacharacters lose their meaning; only ] \ ^ and - need care.
[abc]Any one ofOne character from the list.
/gr[ae]y/g
on “gray grey groy”
matches “gray” “grey”[^abc]None ofOne character that is not in the list (a ^ anywhere but first is literal). Matches line breaks too.
/[^aeiou\s]/g
on “regex”
matches “r” “g” “x”[a-z]RangeCharacters between two code points. Combine ranges: [A-Fa-f0-9] is a hex digit. A - first or last is literal.
/[A-Fa-f0-9]+/g
on “x: 3fA9 zz”
matches “3fA9”\d \DDigit / non-digit\d is a digit, \D anything else.
/\d+/g
on “Order 66, room 101”
matches “66” “101”- Python re: In str patterns \d matches any Unicode digit (e.g. ٣); use re.ASCII for 0-9 only.
- .NET: Matches any Unicode digit unless RegexOptions.ECMAScript is set.
\w \WWord character / non-wordLetters, digits and underscore. In JavaScript and Go that means ASCII only: \w does not match é.
/\w+/g
on “snake_case and kebab-case”
matches “snake_case” “and” “kebab” “case”- PCRE / PHP: ASCII unless PCRE2_UCP (PHP: u modifier plus (*UCP)).
- Python re: Unicode letters and digits by default in str patterns.
- Java: ASCII unless the U flag (UNICODE_CHARACTER_CLASS) is on.
- .NET: Unicode letters, digits and connector punctuation.
\s \SWhitespace / non-whitespaceSpace, tab, line breaks and (in most engines) other Unicode spaces.
/\s+/g
on “a b⇥c”
matches “ ” “⇥”- Go RE2: ASCII whitespace only: \t \n \f \r and space.
[[:alpha:]]POSIX bracket classNamed classes such as [:alpha:], [:digit:], [:space:], [:punct:], used inside brackets.
[[:alpha:]]+- JavaScript: Use [A-Za-z] or \p{L} with the u flag.
- Java: Use \p{Alpha}, \p{Digit}, \p{Punct}.
[\p{L}--[a-z]]Class subtraction / intersectionSet operations inside a class. JavaScript needs the v flag (ES2024): -- subtracts, && intersects.
/[\p{L}--[a-z]]+/gv
on “abcÉtéXYZ”
matches “É” “éXYZ”- PCRE / PHP: PCRE2 10.45+ only, with the (?[ … ]) extended-class syntax.
- Java: Intersection [a-z&&[^aeiou]]; subtraction is written as intersection with a negation.
- .NET: Subtraction [a-z-[aeiou]]; no intersection.
Anchors and boundaries
Anchors match a position, not a character, so they never consume text.
^ $Start / end of string (or line with m)Without the m flag, ^ and $ are the start and end of the whole input; with it, of each line.
/^\w+/gm
on “first line↵second line”
matches “first” “second”- PCRE / PHP: $ also matches before a final \n.
- Python re: $ also matches before a final \n.
- Java: $ also matches before a final line terminator.
- .NET: $ also matches before a final \n.
\bWord boundaryBetween a word character and a non-word character (or the edge of the input). Use it to match whole words.
/\bcat\b/g
on “cat concat cats cat.”
matches “cat” “cat”- JavaScript: ASCII word characters only, even with the u flag.
- Go RE2: ASCII word characters only.
\BNot a word boundaryInside a word, e.g. "cat" only when it is part of a longer word.
/\Bcat/g
on “concat cat bobcat”
matches “cat” “cat”\A \z \ZAbsolute start / endStart and end of the input regardless of multiline mode. \Z also allows a final newline (except in Python, where it is a synonym for \z).
\A\d+\z- JavaScript: Use ^ and $ without the m flag.
- Python re: \A and \z (3.14+); \Z means absolute end, like \z elsewhere.
- Go RE2: \A and \z; no \Z.
\GEnd of previous matchPosition where the last match ended; used to match contiguous runs.
\G\d- JavaScript: No \G; the y (sticky) flag gives the same "start exactly here" behaviour.
Quantifiers: greedy, lazy, possessive
A quantifier repeats the item before it. Greedy (default) takes as much as possible then backs off; lazy (add ?) takes as little as possible; possessive (add +) never backs off.
*Zero or moreRepeat 0 to unlimited times.
/ba*/g
on “b ba baaa”
matches “b” “ba” “baaa”+One or moreRepeat 1 to unlimited times.
/lo+l/g
on “lol loool ll”
matches “lol” “loool”?OptionalZero or one time.
/colou?r/g
on “color colour colouur”
matches “color” “colour”{n}Exactly nExactly n repetitions.
/\d{3}/g
on “12 345 6789”
matches “345” “678”{n,}n or moreAt least n repetitions.
/\d{2,}/g
on “1 22 333”
matches “22” “333”{n,m}Between n and mFrom n to m repetitions, as many as possible.
/\d{2,3}/g
on “1 22 4444”
matches “22” “444”- Go RE2: Counts above 1000 are rejected.
{,m}Up to mZero to m repetitions. Only some engines accept it; elsewhere it is a literal "{,m}" or an error. {0,m} works everywhere.
\d{,3}- JavaScript: Literal text without u, a syntax error with u; write {0,3}.
- PCRE / PHP: PCRE2 10.43+ only.
- Go RE2: Write {0,3}.
- Java: Write {0,3}.
- .NET: Treated as literal text; write {0,3}.
.* .+Greedy (default)Takes the longest possible match, then gives back characters until the rest fits. Here it swallows both tags.
/<.+>/g
on “<b>bold</b>”
matches “<b>bold</b>”*? +? ?? {n,m}?Lazy (non-greedy)Takes the shortest possible match. Usually the fix when a pattern "matches too much".
/<.+?>/g
on “<b>bold</b>”
matches “<b>” “</b>”- Go RE2: Also available as the U flag, which swaps greedy and lazy.
*+ ++ ?+PossessiveGreedy with no backtracking: once matched, characters are never given back. Faster failure, and a defence against catastrophic backtracking.
"[^"]*+"- JavaScript: No possessive quantifiers or atomic groups; emulate with (?=(…))\1.
- Python re: Python 3.11+.
- Go RE2: Not needed: RE2 never backtracks.
- .NET: Use an atomic group (?>…).
Groups and backreferences
Parentheses group items for quantifiers and alternation, and (unless marked non-capturing) save what they matched.
( … )Capturing groupGroups and captures; numbered from 1 by opening parenthesis.
/(\d{3})-(\d{4})/g
on “Call 555-0199 or 555-0123”
matches “555-0199” “555-0123”(?: … )Non-capturing groupGroups without saving, so group numbers stay stable and matching is a little cheaper.
/(?:ab)+/g
on “ababab ab a”
matches “ababab” “ab”(?<name> … )Named groupCaptures under a name you can read back (match.groups.name in JavaScript).
/(?<year>\d{4})-(?<month>\d{2})/g
on “Released 2026-10”
matches “2026-10”- PCRE / PHP: Also (?'name'…) and (?P<name>…).
- Python re: Only (?P<name>…).
- Go RE2: (?P<name>…); (?<name>…) also accepted since Go 1.22.
- .NET: Also (?'name'…).
\1Backreference by numberMatches the same text a group captured earlier.
/(\w)\1/g
on “bookkeeper”
matches “oo” “kk” “ee”- Go RE2: RE2 has no backreferences (they would break its linear-time guarantee).
\k<name>Backreference by nameSame as \1 but by name. The example matches text in matching quotes.
/(?<q>['"]).*?\k<q>/g
on “say "hi" or 'yo'”
matches “"hi"” “'yo'”- PCRE / PHP: Also \k{name}, \g{name} and (?P=name).
- Python re: Write (?P=name).
a|bAlternation (or)Either side. Alternatives are tried left to right, so put longer ones first when one is a prefix of another.
/cat|dog/g
on “hotdog catalog”
matches “dog” “cat”(?> … )Atomic groupOnce the group has matched, the engine will not backtrack into it.
(?>a|ab)c- Python re: Python 3.11+.
- Go RE2: Not needed: RE2 never backtracks.
(?i) (?i: … )Inline flagsTurn flags on or off inside the pattern. (?i) applies to the rest of the pattern; (?i:…) only to the group; (?-i:…) turns a flag off.
/(?i:hello) world/g
on “HELLO world HELLO WORLD”
matches “HELLO world”- JavaScript: Only the scoped (?i:…) / (?-i:…) form, for i, m and s (ES2025). (?i) at the start is a syntax error.
- Python re: Global (?i) must be at the very start of the pattern (an error elsewhere since 3.11); (?i:…) works anywhere.
(?(1)yes|no)ConditionalMatches "yes" if group 1 participated, otherwise "no".
(<)?\w+(?(1)>)(?R) (?1)Recursion / subroutineRe-enters the whole pattern or a group, for nested structures such as balanced parentheses.
\((?:[^()]|(?R))*\)- Python re: Available in the third-party regex module.
- .NET: No recursion; balancing groups (?<open-close>…) handle nesting.
(?# … )Inline commentIgnored by the engine. For longer comments use the x (extended) flag.
\d{3}(?#area code)Lookahead and lookbehind
Lookarounds check what is next to the current position without including it in the match. They are zero-width, like anchors.
(?= … )Positive lookaheadFollowed by … (not included in the match).
/\d+(?=px)/g
on “10px 20em 30px”
matches “10” “30”- Go RE2: RE2 has no lookaround of any kind.
(?! … )Negative lookaheadNot followed by …. The \d inside stops the engine from giving back digits to make the check pass.
/\d+(?!px|\d)/g
on “10px 20em”
matches “20”(?<= … )Positive lookbehindPreceded by … (not included in the match).
/(?<=\$)\d+(?:\.\d\d)?/g
on “Cost: $42.50 or 42”
matches “42.50”- JavaScript: Any length (ES2018).
- PCRE / PHP: Each alternative must have a bounded length; variable length (max 255 by default) since PCRE2 10.43.
- Python re: Fixed width only: (?<=ab|cd) is fine, (?<=a+) is an error.
- Java: Bounded length only: no * or + inside.
- .NET: Any length.
(?<! … )Negative lookbehindNot preceded by ….
/(?<!\$)\b\d+\b/g
on “$30 and 45”
matches “45”- PCRE / PHP: Same length rules as positive lookbehind.
- Python re: Fixed width only.
- Java: Bounded length only.
\KReset match startDrops everything matched so far from the result; a lookbehind without length limits.
price: \K\d+- JavaScript: Use (?<=…) or a capture group.
Flags (modifiers)
JavaScript writes flags after the closing slash (/x/gi). Other languages pass constants (re.I, Pattern.CASE_INSENSITIVE, RegexOptions.IgnoreCase) or use inline (?i).
gGlobal (all matches)Find every match instead of stopping at the first. Required by matchAll and replaceAll.
/o/g
on “foo boo”
matches “o” “o” “o” “o”- PCRE / PHP: No flag: use preg_match_all() / preg_replace().
- Python re: No flag: use re.findall(), re.finditer(), re.sub().
- Go RE2: No flag: use the FindAll… methods.
- Java: No flag: loop with matcher.find().
- .NET: No flag: use Regex.Matches().
iIgnore caseCase-insensitive matching.
/hello/gi
on “Hello HELLO hello”
matches “Hello” “HELLO” “hello”- Python re: re.I / re.IGNORECASE or (?i).
- Java: CASE_INSENSITIVE (ASCII unless UNICODE_CASE) or (?i).
- .NET: RegexOptions.IgnoreCase or (?i).
mMultiline^ and $ match at line starts and ends, not just the ends of the input.
/^-\s.+$/gm
on “- one↵- two↵three”
matches “- one” “- two”- Python re: re.M / re.MULTILINE.
- .NET: RegexOptions.Multiline.
sDot matches newlineMakes . match line breaks too. Without it, [\s\S] is the portable "anything".
/<p>.*?</p>/gs
on “<p>a↵b</p>”
matches “<p>a↵b</p>”- Python re: re.S / re.DOTALL.
- Java: Pattern.DOTALL.
- .NET: Called RegexOptions.Singleline.
xExtended (free spacing)Whitespace in the pattern is ignored and # starts a comment, so long patterns can be laid out over lines.
(?x) \d{3} - \d{4} # local number- Python re: re.X / re.VERBOSE.
- Java: Pattern.COMMENTS.
- .NET: RegexOptions.IgnorePatternWhitespace.
uUnicodeTreats the input as code points (so . matches a whole emoji), enables \p{…} and \u{…}, and makes invalid escapes errors.
/^.$/gu
on “😀”
matches “😀”- PCRE / PHP: PHP u modifier (UTF-8 mode); add (*UCP) for Unicode \w and \d.
- Python re: No flag needed: str patterns are Unicode; re.ASCII opts out.
- Go RE2: No flag: Go always works on UTF-8 code points.
- Java: UNICODE_CASE and UNICODE_CHARACTER_CLASS (U).
- .NET: No flag: always UTF-16 code units (an emoji is two).
vUnicode setsES2024 upgrade of u: class set operations (--, &&), nested classes and string properties such as \p{RGI_Emoji}. Cannot be combined with u.
/[\p{L}&&\p{ASCII}]+/gv
on “Ünïcode text”
matches “n” “code” “text”yStickyEach match must start exactly where the previous one ended (lastIndex). Useful for tokenizers.
/\d/gy
on “12a3”
matches “1” “2”- PCRE / PHP: Use \G.
- Python re: Use pattern.match(text, pos).
- Java: Use \G or matcher.lookingAt().
- .NET: Use \G.
dMatch indicesAdds match.indices with the start and end of every capture group (ES2022).
/(?<y>\d{4})/d- PCRE / PHP: Offsets always available (PREG_OFFSET_CAPTURE).
- Python re: Always available: m.span(n).
- Go RE2: Always available: FindStringSubmatchIndex.
- Java: Always available: matcher.start(n) / end(n).
- .NET: Always available: Group.Index / Length.
Unicode properties \p{…}
Property escapes match characters by Unicode category or script, which is the only reliable way to match "any letter" across languages. In JavaScript they need the u or v flag.
\p{L}Any letterLetters in every script: é, ß, 東, д.
/\p{L}+/gu
on “naïve café 東京 123”
matches “naïve” “café” “東京”- PCRE / PHP: PHP needs the u modifier for UTF-8 input.
- Python re: Use the third-party regex module, or [^\W\d_] for "letters".
\p{Lu} \p{Ll}Uppercase / lowercase letterGeneral categories: Lu uppercase, Ll lowercase, N number, P punctuation, S symbol, Z separator.
/\p{Lu}/gu
on “Élan Vital”
matches “É” “V”\P{…}Not in propertyCapital P negates: \P{L} is anything that is not a letter.
/\P{L}+/gu
on “abc-123”
matches “-123”\pLOne-letter shorthandSingle-letter categories without braces.
\pL+- JavaScript: Braces are required: \p{L}.
- .NET: Braces are required: \p{L}.
\p{Script=Greek}ScriptCharacters of one writing system. sc= is the short form; Script_Extensions (scx=) also includes characters shared between scripts.
/\p{Script=Greek}+/gu
on “alpha α, beta β”
matches “α” “β”- PCRE / PHP: \p{Greek}, \p{sc:Greek} or \p{scx:Greek}.
- Go RE2: \p{Greek}.
- Java: Write \p{script=Greek}, \p{sc=Greek} or \p{IsGreek}.
- .NET: Only named blocks such as \p{IsGreek} (a code range, not the script).
\p{sc=Han}Chinese / Japanese kanjiHan ideographs. For Japanese kana add \p{sc=Hiragana} and \p{sc=Katakana}.
/\p{sc=Han}+/gu
on “Tokyo 東京 2026 中文”
matches “東京” “中文”- PCRE / PHP: \p{Han}.
- Python re: Use a range such as [\u4e00-\u9fff] (covers the main block only).
- Go RE2: \p{Han}.
- Java: Also \p{IsHan}.
- .NET: Blocks only, e.g. \p{IsCJKUnifiedIdeographs}.
\p{RGI_Emoji}Emoji (whole sequences)With the v flag, matches complete emoji including skin tones and family sequences. With u, \p{Extended_Pictographic} matches single pictographs only.
/\p{RGI_Emoji}/gv
on “Go 👍🏽 team 👨👩👧!”
matches “👍🏽” “👨👩👧”- PCRE / PHP: Single code points via Boolean properties in recent PCRE2 (10.40+); no sequence property.
- Java: \p{IsEmoji} matches single code points (Java 21+).
\XGrapheme clusterOne user-perceived character, e.g. e + combining accent, or a flag emoji.
\X- JavaScript: Use Intl.Segmenter for grapheme splitting.
- Python re: Available in the regex module.
Substitution (replacement) syntax
What to type in the replacement string. This is where languages differ most, so the column for your language matters more than the JavaScript example.
$&Whole matchInserts the entire matched text.
/\d+/g
on “3 apples, 12 pears”
replace with “[$&]” → “[3] apples, [12] pears”- PCRE / PHP: $0 or \0 in preg_replace.
- Python re: \g<0>.
- Go RE2: ${0} or $0 (Expand / ReplaceAllString).
- Java: $0.
- .NET: Also $0.
$1Numbered groupInserts what group 1 captured. Swap two words:
/(\w+)\s(\w+)/g
on “hello world”
replace with “$2 $1” → “world hello”- PCRE / PHP: Also \1 and ${1}.
- Python re: \1 or \g<1> (use a raw string r"\1").
- Go RE2: Use ${1}x when a letter or digit follows, or Go reads $1x as a group named "1x".
$<name>Named groupInserts a named group. Reformat an ISO date as day/month/year:
/(?<y>\d{4})-(?<m>\d{2})-(?<d>\d{2})/g
on “2026-10-18”
replace with “$<d>/$<m>/$<y>” → “18/10/2026”- PCRE / PHP: preg_replace has no named references; use the group number or preg_replace_callback().
- Python re: \g<name>.
- Go RE2: ${name} (or $name).
- Java: ${name}.
- .NET: ${name}.
$$Literal dollar signEscapes $ in the replacement.
/(\d+)/g
on “Price: 20”
replace with “$$$1” → “Price: $20”- PCRE / PHP: A $ not followed by a digit or { is already literal; write ${1} after it.
- Python re: $ is not special; escape backslashes as \\.
- Java: \$ (Matcher.quoteReplacement() escapes a whole string).
$` $'Text before / after the matchInserts the input before or after the match. Rarely needed, but occasionally handy.
/=/
on “key=value”
replace with “ is set ($') and was ($`) ” → “key is set (value) and was (key) value”Common recipes (with honest caveats)
Patterns people search for most, written to be readable and safe from catastrophic backtracking. Each says what it does not do.
Email (practical)Find email-like stringsLocal part, @, and a domain with at least one dot.
/[\w.+-]+@[\w-]+(?:\.[\w-]+)+/g
on “Write to ana.lee+news@example.co.uk or bob@test.dev.”
matches “ana.lee+news@example.co.uk” “bob@test.dev”Caveat: Rejects valid but rare addresses (quoted local parts, non-ASCII domains) and accepts some invalid ones (a..b@x.y). No regex can tell you a mailbox exists: send a confirmation email.
URLFind http(s) links in textStops at whitespace, quotes and angle brackets, and drops trailing punctuation such as a full stop or comma.
/https?://[^\s<>"]*[^\s<>".,;:!?)]/g
on “See https://example.com/a?b=1, or (http://test.dev/x).”
matches “https://example.com/a?b=1” “http://test.dev/x”Caveat: Good for linkifying text, not for validation. To check a URL, use the URL parser of your language (new URL() in JavaScript) and test its protocol and host.
IPv4 addressFour octets 0–255Each octet limited to 0–255 without leading zeros.
/\b(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}\b/g
on “10.0.0.1 256.1.1.1 192.168.1.254”
matches “10.0.0.1” “192.168.1.254”Caveat: Does not handle IPv6, CIDR suffixes or ports. For validation use an IP parser (Python ipaddress, Go net/netip, Node net.isIP).
Date YYYY-MM-DDISO 8601 calendar dateMonth 01–12 and day 01–31.
/\b\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])\b/g
on “2026-10-18, 2026-13-01, 2026-02-31”
matches “2026-10-18” “2026-02-31”Caveat: Shape only: 2026-02-31 passes. Parse the date with a date library to reject impossible days.
Date MM/DD/YYYYUS-style dateOne- or two-digit month and day, four-digit year.
/\b(?:0?[1-9]|1[0-2])/(?:0?[1-9]|[12]\d|3[01])/\d{4}\b/g
on “Due 10/18/2026 or 1/5/2027, not 13/01/2026”
matches “10/18/2026” “1/5/2027”Caveat: 01/02/2026 is 2 January in the US and 1 February almost everywhere else; a regex cannot know which was meant.
Phone (North America)(416) 555-0199 and variantsTen digits with optional parentheses, spaces, dots or dashes.
/\(?\b\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}\b/g
on “(416) 555-0199, 416.555.0199, 4165550199”
matches “(416) 555-0199” “416.555.0199” “4165550199”Caveat: North American numbers only. For international numbers use a library such as libphonenumber; store numbers in E.164 form (next row).
Phone (E.164)International format +CC…A plus sign, a country code that does not start with 0, up to 15 digits in total.
/^\+[1-9]\d{1,14}$/gm
on “+14165550199↵+447911123456↵0044791112”
matches “+14165550199” “+447911123456”Caveat: Checks the E.164 shape, not whether the number is assigned or the right length for its country.
Hex colour#rgb, #rgba, #rrggbb, #rrggbbaaThe four lengths CSS accepts.
/#(?:[\da-fA-F]{8}|[\da-fA-F]{6}|[\da-fA-F]{3,4})\b/g
on “#fff #244b3f #12345 #ff000080 #1234567”
matches “#fff” “#244b3f” “#ff000080”Caveat: Matches inside longer text such as URLs with #fragments too; anchor with ^…$ to validate a single value.
URL sluglowercase-words-with-hyphensLowercase letters and digits separated by single hyphens.
/^[a-z0-9]+(?:-[a-z0-9]+)*$/gm
on “my-post-2026↵My Post↵-bad-↵good”
matches “my-post-2026” “good”Caveat: ASCII only. To create slugs from titles, use the URL slug generator rather than a regex.
Trim whitespaceLeading and trailing spacesReplace with an empty string. Without the m flag, ^ and $ are the ends of the whole text.
/^\s+|\s+$/g
on “ padded text ”
replace with “” → “padded text”Caveat: Every modern language has a built-in trim() that is faster and clearer; use the regex only where you cannot call code (editors, config files).
Collapse spacesRuns of spaces to oneReplace two or more spaces or tabs with a single space.
/[ \t]{2,}/g
on “too many ⇥ spaces”
replace with “ ” → “too many spaces”Duplicate wordsthe the, is isA word followed by itself. With i, "The the" is caught too.
/\b(\w+)\s+\1\b/gi
on “This is is a test test of The the editor”
matches “is is” “test test” “The the”Caveat: Needs backreferences, so it does not work in Go. "had had" and "that that" are sometimes correct English.
Password rulesLowercase, uppercase, digit, 12+ charactersEach lookahead checks one rule from the start; .{12,} sets the length.
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{12,}$/gm
on “short1A↵alllowercase123↵GoodPassword42”
matches “GoodPassword42”Caveat: NIST SP 800-63B advises against composition rules: require length and check against breached-password lists instead.
UUID8-4-4-4-12 hexVersions 1–8 with the RFC 9562 variant bits.
/\b[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\b/gi
on “id 3f2b8c1e-9d4a-4b7e-8f6a-1c2d3e4f5a6b and 00000000-0000-0000-0000-000000000000”
matches “3f2b8c1e-9d4a-4b7e-8f6a-1c2d3e4f5a6b”Caveat: Rejects the nil UUID (all zeros) and the max UUID (all f), which are valid special values.
A static reference: searching and filtering happen in your browser, and Try it links open our in-browser regex tester. Browse all free tools.
Found a problem, or something that could be better? We read every message and we fix things quickly.
This regex cheat sheet lists every regular expression token you are likely to need, from \d and \b to lookbehind, possessive quantifiers and \p{Script=Greek}, each with a short explanation and an example that shows exactly what it matches. Every example has a Try it link that opens our regex tester with the pattern, flags and sample text already filled in, so you can change it and watch the matches move.
Regex looks the same everywhere but is not. Lookbehind is unlimited in JavaScript and .NET, fixed-width in Python, bounded in Java and PCRE, and missing in Go. Python spells named groups (?P<name>…), PHP cannot use names in a replacement, and only some engines know \A, \K or (?R). The flavour picker shows each token's support in JavaScript, PCRE/PHP, Python, Go, Java and .NET, with the alternative syntax where one exists. The examples themselves run in JavaScript; for the other languages, read the notes and test in that language before you ship.
How to use
- Search for a token (\b, lookahead) or a task (email, trim, duplicate words), or jump to a section from the chips at the top.
- Pick your language in the flavour bar. Tokens it does not support are dimmed, and the note under each entry gives the syntax your language uses instead.
- Click Try it in the regex tester to run the example live, then edit the pattern or the text there.
- Use the # next to an entry to link straight to it, or Print / Save as PDF for a compact two-column copy.
Frequently asked questions
What is the difference between greedy and lazy quantifiers?
A greedy quantifier (*, +, {n,m}) takes as many characters as it can and then gives some back if the rest of the pattern fails; a lazy one (*?, +?, {n,m}?) takes as few as possible. On <b>bold</b>, <.+> matches the whole string while <.+?> matches <b> and </b> separately. Possessive quantifiers (*+, ++) are greedy and never give characters back; JavaScript, Go and .NET do not have them.
Which languages support lookbehind?
JavaScript (since ES2018) and .NET allow lookbehind of any length. Java requires a bounded maximum length, so no * or + inside. Python's re module accepts only fixed-width lookbehind. PCRE2 required each alternative to have a fixed length until 10.43, which added variable-length lookbehind up to a limit (255 characters by default). Go's RE2 engine has no lookahead or lookbehind at all.
How do I match any letter, including accented and non-Latin letters?
Use the Unicode property \p{L}. In JavaScript it needs the u or v flag (/\p{L}+/u); PCRE, Go, Java and .NET support it directly. [a-zA-Z] misses é, ß and every non-Latin script, and \w is ASCII-only in JavaScript and Go. Python's built-in re has no \p{…}; use the third-party regex module, or [^\W\d_], which in Python 3 matches Unicode letters.
How do I use a captured group in the replacement?
It depends on the language: $1 in JavaScript, Java, .NET, Go and PHP; \1 or \g<1> in Python. Named groups are $<name> in JavaScript, ${name} in Java, .NET and Go, and \g<name> in Python; PHP's preg_replace has no named form, so use the number. The whole match is $& in JavaScript and .NET, $0 in Java and PHP, and \g<0> in Python.
Why does my regex work in JavaScript but not in Python (or the other way round)?
The usual culprits: named groups ((?<name>) in JavaScript, (?P<name>) in Python), \p{…} properties (JavaScript yes, Python re no), lookbehind length (any in JavaScript, fixed in Python), inline flags ((?i) at the start works in Python but is an error in JavaScript, which only has the scoped (?i:…)), and \d or \w matching Unicode digits and letters in Python but only ASCII in JavaScript. Also remember Python string escaping: write patterns as raw strings, r"\d+".
Is it safe to validate email addresses with a regex?
Only as a shape check. A practical pattern such as [\w.+-]+@[\w-]+(?:\.[\w-]+)+ catches typos, but it rejects some valid addresses (quoted local parts, internationalised domains) and accepts some invalid ones. No pattern can tell you that a mailbox exists, so check the shape loosely and then send a confirmation email.
Writing patterns that work in more than one language
If a pattern must run in several engines (a shared validation rule, a config file read by services in different languages), stay inside the common subset. These behave the same in all six engines on this page:
• Literal characters, escapes such as \. and \$, and the classes [abc], [^abc] and [a-z].
• \d, \s and \w, as long as your input is ASCII (Python and .NET match Unicode digits and letters too).
• ^ and $, \b, alternation, capturing and non-capturing groups.
• Greedy and lazy quantifiers: *, +, ?, {n}, {n,m} and their ? forms.
Leave out lookaround (Go has none), backreferences (Go), possessive quantifiers and atomic groups (JavaScript, Go and .NET lack one or both), named groups (Python's syntax differs) and \p{…} (Python's re lacks it). When you need one of those, keep one copy of the pattern per language and test each.
Avoiding catastrophic backtracking
Backtracking engines (JavaScript, PCRE, Python, Java, .NET) can take exponential time on patterns where a quantified group can match the same text in many ways, such as (a+)+$ or (\w|\d)*x. On a long input that almost matches, the engine tries every split before failing, and a web server can hang on one request. This is the regular expression denial of service (ReDoS) problem.
The fixes are mechanical: avoid nesting quantifiers over the same characters; make alternatives mutually exclusive; prefer a negated class such as [^"]* to .*? when you know the delimiter; use possessive quantifiers or atomic groups where your engine has them; and cap input length before matching. .NET also offers RegexOptions.NonBacktracking and a match timeout, PCRE has match limits you can set, and Go's RE2 engine guarantees linear time by not supporting the features that need backtracking.
Escaping regex inside strings
Most regex bugs in real code are string-escaping bugs, not regex bugs. The backslash is special to both the language's string literal and the regex engine, so a pattern written as a normal string needs double backslashes.
• JavaScript: a literal /\d+/ needs one backslash; new RegExp("\\d+") needs two. String.raw`\d+` avoids the doubling.
• Python: always use raw strings, r"\d+"; otherwise "\b" is a backspace character, not a word boundary.
• Java and C#: "\\d+" in ordinary strings (Java text blocks process escapes too); C# verbatim strings, @"\d+", keep backslashes as typed.
• Go: backtick raw strings, `\d+`, are the norm with regexp.MustCompile.
• PHP: patterns include delimiters, '/\d+/', and single-quoted strings keep most backslashes as typed.
Related free tools
- Regex Tester — Test a regular expression against sample text with live match highlighting, capture groups and replace preview. Free, in your browser.
- Git Cheat Sheet — Git commands organised by what you want to do: undo the last commit, rename a branch, delete a remote branch. Modern switch/restore with classic equivalents and danger badges.
- Markdown Cheat Sheet — Every Markdown element with source and rendered preview, extended syntax (tables, task lists, footnotes, math, Mermaid, alerts), a 9-platform compatibility table and a live playground.
- Cron Expression Generator — Build a cron schedule from dropdowns or paste one, read it in plain English, and see the next 10 run times in your zone and UTC. Free, in your browser.
- Diff Checker — Compare two versions of a text, code or JSON file and see exactly which lines, words and characters changed.