Loading...
^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ • ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ • ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ • ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ • ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ • ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ • ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ • ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ • ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ • ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ • ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ • ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ • ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ • ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ • ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ • ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ • ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ • ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ • ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ • ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b • \b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b • \b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b • \b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b • \b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b • \b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b • \b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b • \b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b • \b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b • \b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b • \b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b • \b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b • \b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b • \b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b • \b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b • \b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b • \b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b • \b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b • \b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b • \b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b
^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)[A-Za-z\d@$!%*?&]{8,}$ • ^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)[A-Za-z\d@$!%*?&]{8,}$ • ^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)[A-Za-z\d@$!%*?&]{8,}$ • ^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)[A-Za-z\d@$!%*?&]{8,}$ • ^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)[A-Za-z\d@$!%*?&]{8,}$ • ^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)[A-Za-z\d@$!%*?&]{8,}$ • ^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)[A-Za-z\d@$!%*?&]{8,}$ • ^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)[A-Za-z\d@$!%*?&]{8,}$ • ^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)[A-Za-z\d@$!%*?&]{8,}$ • ^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)[A-Za-z\d@$!%*?&]{8,}$ • ^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)[A-Za-z\d@$!%*?&]{8,}$ • ^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)[A-Za-z\d@$!%*?&]{8,}$ • ^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)[A-Za-z\d@$!%*?&]{8,}$ • ^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)[A-Za-z\d@$!%*?&]{8,}$ • ^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)[A-Za-z\d@$!%*?&]{8,}$ • ^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)[A-Za-z\d@$!%*?&]{8,}$ • ^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)[A-Za-z\d@$!%*?&]{8,}$ • ^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)[A-Za-z\d@$!%*?&]{8,}$ • ^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)[A-Za-z\d@$!%*?&]{8,}$ • ^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)[A-Za-z\d@$!%*?&]{8,}$
(https?:\/\/)?([\w-]+\.)+[\w-]+(\/[\w-./?%&=]*)? • (https?:\/\/)?([\w-]+\.)+[\w-]+(\/[\w-./?%&=]*)? • (https?:\/\/)?([\w-]+\.)+[\w-]+(\/[\w-./?%&=]*)? • (https?:\/\/)?([\w-]+\.)+[\w-]+(\/[\w-./?%&=]*)? • (https?:\/\/)?([\w-]+\.)+[\w-]+(\/[\w-./?%&=]*)? • (https?:\/\/)?([\w-]+\.)+[\w-]+(\/[\w-./?%&=]*)? • (https?:\/\/)?([\w-]+\.)+[\w-]+(\/[\w-./?%&=]*)? • (https?:\/\/)?([\w-]+\.)+[\w-]+(\/[\w-./?%&=]*)? • (https?:\/\/)?([\w-]+\.)+[\w-]+(\/[\w-./?%&=]*)? • (https?:\/\/)?([\w-]+\.)+[\w-]+(\/[\w-./?%&=]*)? • (https?:\/\/)?([\w-]+\.)+[\w-]+(\/[\w-./?%&=]*)? • (https?:\/\/)?([\w-]+\.)+[\w-]+(\/[\w-./?%&=]*)? • (https?:\/\/)?([\w-]+\.)+[\w-]+(\/[\w-./?%&=]*)? • (https?:\/\/)?([\w-]+\.)+[\w-]+(\/[\w-./?%&=]*)? • (https?:\/\/)?([\w-]+\.)+[\w-]+(\/[\w-./?%&=]*)? • (https?:\/\/)?([\w-]+\.)+[\w-]+(\/[\w-./?%&=]*)? • (https?:\/\/)?([\w-]+\.)+[\w-]+(\/[\w-./?%&=]*)? • (https?:\/\/)?([\w-]+\.)+[\w-]+(\/[\w-./?%&=]*)? • (https?:\/\/)?([\w-]+\.)+[\w-]+(\/[\w-./?%&=]*)? • (https?:\/\/)?([\w-]+\.)+[\w-]+(\/[\w-./?%&=]*)?
#([0-9a-fA-F]{3}){1,2}\b • #([0-9a-fA-F]{3}){1,2}\b • #([0-9a-fA-F]{3}){1,2}\b • #([0-9a-fA-F]{3}){1,2}\b • #([0-9a-fA-F]{3}){1,2}\b • #([0-9a-fA-F]{3}){1,2}\b • #([0-9a-fA-F]{3}){1,2}\b • #([0-9a-fA-F]{3}){1,2}\b • #([0-9a-fA-F]{3}){1,2}\b • #([0-9a-fA-F]{3}){1,2}\b • #([0-9a-fA-F]{3}){1,2}\b • #([0-9a-fA-F]{3}){1,2}\b • #([0-9a-fA-F]{3}){1,2}\b • #([0-9a-fA-F]{3}){1,2}\b • #([0-9a-fA-F]{3}){1,2}\b • #([0-9a-fA-F]{3}){1,2}\b • #([0-9a-fA-F]{3}){1,2}\b • #([0-9a-fA-F]{3}){1,2}\b • #([0-9a-fA-F]{3}){1,2}\b • #([0-9a-fA-F]{3}){1,2}\b
\b(\w+)\s+\1\b • \b(\w+)\s+\1\b • \b(\w+)\s+\1\b • \b(\w+)\s+\1\b • \b(\w+)\s+\1\b • \b(\w+)\s+\1\b • \b(\w+)\s+\1\b • \b(\w+)\s+\1\b • \b(\w+)\s+\1\b • \b(\w+)\s+\1\b • \b(\w+)\s+\1\b • \b(\w+)\s+\1\b • \b(\w+)\s+\1\b • \b(\w+)\s+\1\b • \b(\w+)\s+\1\b • \b(\w+)\s+\1\b • \b(\w+)\s+\1\b • \b(\w+)\s+\1\b • \b(\w+)\s+\1\b • \b(\w+)\s+\1\b
^\+?[1-9]\d{1,14}$ • ^\+?[1-9]\d{1,14}$ • ^\+?[1-9]\d{1,14}$ • ^\+?[1-9]\d{1,14}$ • ^\+?[1-9]\d{1,14}$ • ^\+?[1-9]\d{1,14}$ • ^\+?[1-9]\d{1,14}$ • ^\+?[1-9]\d{1,14}$ • ^\+?[1-9]\d{1,14}$ • ^\+?[1-9]\d{1,14}$ • ^\+?[1-9]\d{1,14}$ • ^\+?[1-9]\d{1,14}$ • ^\+?[1-9]\d{1,14}$ • ^\+?[1-9]\d{1,14}$ • ^\+?[1-9]\d{1,14}$ • ^\+?[1-9]\d{1,14}$ • ^\+?[1-9]\d{1,14}$ • ^\+?[1-9]\d{1,14}$ • ^\+?[1-9]\d{1,14}$ • ^\+?[1-9]\d{1,14}$
(?<=@)\w+(?=\.) • (?<=@)\w+(?=\.) • (?<=@)\w+(?=\.) • (?<=@)\w+(?=\.) • (?<=@)\w+(?=\.) • (?<=@)\w+(?=\.) • (?<=@)\w+(?=\.) • (?<=@)\w+(?=\.) • (?<=@)\w+(?=\.) • (?<=@)\w+(?=\.) • (?<=@)\w+(?=\.) • (?<=@)\w+(?=\.) • (?<=@)\w+(?=\.) • (?<=@)\w+(?=\.) • (?<=@)\w+(?=\.) • (?<=@)\w+(?=\.) • (?<=@)\w+(?=\.) • (?<=@)\w+(?=\.) • (?<=@)\w+(?=\.) • (?<=@)\w+(?=\.)
🧬 The Complete Regex Reference

RegexRef

by One4.dev

Master regular expressions with an interactive playground, comprehensive token reference, and real-world patterns across JavaScript, Python, Go, and Rust.

K

Regex Building Blocks

The essential tokens you need to build any regular expression. Each card shows the syntax, a plain-English description, and a live example.

Anchors

^
Start of Line

Matches the beginning of the string, or the beginning of a line when the multiline flag (m) is enabled.

Example:/^hello/gm
hello world
Inside a character class [^...], the caret negates the set instead.
$
End of Line

Matches the end of the string, or the end of a line when the multiline flag (m) is enabled.

Example:/world$/gm
hello world
\b
Word Boundary

Matches a position between a word character (\w) and a non-word character (\W), or at the start/end of the string.

Example:/\bcat\b/g
cat concatenate
Useful for matching whole words only. Zero-width assertion — matches a position, not a character.
\B
Non-Word Boundary

Matches a position that is NOT a word boundary — i.e. between two word characters or two non-word characters.

Example:/\Bcat\B/g
cat concatenate
The opposite of \b. Matches "cat" inside "concatenate" but not the standalone word "cat".

Quantifiers

*
Zero or More

Matches the preceding element zero or more times. Greedy by default — matches as many as possible.

Example:/ab*c/g
ac abc abbc
+
One or More

Matches the preceding element one or more times. Greedy by default.

Example:/ab+c/g
ac abc abbc
?
Zero or One

Matches the preceding element zero or one time. Makes the element optional.

Example:/colou?r/g
color colour
{n}
Exactly N

Matches the preceding element exactly n times.

Example:/a{3}b/g
aab aaab aaaab
{n,}
N or More

Matches the preceding element n or more times. Greedy by default.

Example:/a{2,}b/g
aab aaab aaaab
{n,m}
Between N and M

Matches the preceding element at least n and at most m times. Greedy by default.

Example:/a{2,3}b/g
ab aab aaab aaaab
*?
Lazy Zero or More

Matches the preceding element zero or more times, but as few times as possible (lazy/non-greedy).

Example:/<.*?>/g
<b>bold</b>
Without the ?, the greedy version <.*> would match the entire string as one match.
+?
Lazy One or More

Matches the preceding element one or more times, but as few times as possible (lazy/non-greedy).

Example:/<.+?>/g
<b>bold</b>
??
Lazy Zero or One

Matches the preceding element zero or one time, preferring zero (lazy/non-greedy).

Example:/colou??r/g
color colour
Prefers matching without the optional element when possible.

Character Classes

.
Any Character

Matches any single character except newline (\n). With the s (dotAll) flag, it also matches newlines.

Example:/c.t/g
cat cot cut
\d
Digit

Matches any digit character (0-9). Equivalent to [0-9].

Example:/\d+/g
abc 123 def
\D
Non-Digit

Matches any character that is NOT a digit. Equivalent to [^0-9].

Example:/\D+/g
abc 123 def
\w
Word Character

Matches any word character: letters, digits, and underscore. Equivalent to [a-zA-Z0-9_].

Example:/\w+/g
hello world!
\W
Non-Word Character

Matches any character that is NOT a word character. Equivalent to [^a-zA-Z0-9_].

Example:/\W+/g
hello world!
\s
Whitespace

Matches any whitespace character: space, tab, newline, carriage return, form feed, and vertical tab.

Example:/\s/g
hello world
\S
Non-Whitespace

Matches any character that is NOT a whitespace character.

Example:/\S+/g
hello world
[abc]
Character Set

Matches any one of the characters inside the brackets. Characters are treated literally (except ], \, ^, -).

Example:/[cb]at/g
cat bat rat
[^abc]
Negated Character Set

Matches any single character that is NOT listed inside the brackets.

Example:/[^cb]at/g
cat bat rat
[a-z]
Character Range

Matches any character in the specified range. Multiple ranges can be combined, e.g. [a-zA-Z].

Example:/[a-z]+/g
Hello World 123
[0-9]
Digit Range

Matches any digit in the specified range. Equivalent to \d when using [0-9].

Example:/[0-9]+/g
abc 123 def 456

Special Characters

|
Alternation

Acts as a boolean OR, matching either the expression before or after the pipe. Use groups to limit scope.

Example:/cat|dog/g
cat dog bird
Without grouping, alternation applies to the entire expression on each side. Use (?:a|b) to constrain it.
\
Escape Character

Escapes the next character, treating it as a literal instead of a special regex character.

Example:/\$\d+\.\d+/g
price is $9.99
Characters that need escaping: . * + ? ^ $ { } [ ] ( ) | \

Capturing & Lookaround

Group sub-expressions, extract captures, and use zero-width assertions to match patterns based on context without consuming characters.

Capturing Groups

(...)
Capturing Group

Groups part of the pattern and captures the matched substring for later use via backreferences or match results.

Example:/(\d{4})-(\d{2})-(\d{2})/
2024-01-15
Captured groups are numbered left-to-right starting at 1. Group 0 is always the entire match.
(?:...)
Non-Capturing Group

Groups part of the pattern without capturing the matched text. Useful for applying quantifiers to a group without saving the match.

Example:/(?:http|https):///g
http://example.com https://example.com
More efficient than capturing groups when you don't need the matched content.
(?<name>...)
Named Capturing Group

Creates a capturing group with a name, making matches accessible by name instead of just by number.

Example:/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/
2024-01-15
Python uses (?P<name>...) syntax. Go also uses (?P<name>...). JavaScript and Rust use (?<name>...).
\1
Backreference

Matches the same text that was previously matched by the specified capturing group number.

Example:/(\w+) \1/g
hello hello world
Not supported in Go (RE2 engine). Use \k<name> for named backreferences in JavaScript.

Lookahead & Lookbehind

(?=...)
Positive Lookahead

Asserts that what follows the current position matches the pattern inside. Does not consume characters.

Example:/\w+(?=\d)/g
foo123 bar456
Zero-width assertion. Not supported in Go (RE2 engine). Useful for matching patterns that must be followed by something.
(?!...)
Negative Lookahead

Asserts that what follows the current position does NOT match the pattern inside. Does not consume characters.

Example:/\b\w+\b(?!\d)/g
foo bar123
Matches words NOT followed by digits. Not supported in Go (RE2 engine).
(?<=...)
Positive Lookbehind

Asserts that what precedes the current position matches the pattern inside. Does not consume characters.

Example:/(?<=\$)\d+/g
$100 €200 $300
Matches digits preceded by $. Not supported in Go (RE2 engine). Some engines require fixed-width lookbehinds.
(?<!...)
Negative Lookbehind

Asserts that what precedes the current position does NOT match the pattern inside. Does not consume characters.

Example:/(?<!\$)\d+/g
$100 200 $300
Matches digits NOT preceded by $. Not supported in Go (RE2 engine).

Regex Flags

Flags modify how the regex engine interprets your pattern. Not all flags are available in every language — see the compatibility matrix below.

FlagNameDescriptionJSPythonGoRust
gGlobalFind all matches rather than stopping after the first match.re.findall() / re.finditer()FindAllString()captures_iter() / find_iter()
iCase InsensitiveMakes the pattern case-insensitive, matching both uppercase and lowercase letters.re.IGNORECASE(?i) inline flag(?i) inline flag
mMultilineMakes ^ and $ match the start and end of each line, not just the start and end of the entire string.re.MULTILINE(?m) inline flag(?m) inline flag
sDotAll / Single LineMakes the dot (.) match any character including newline characters (\n, \r).re.DOTALL(?s) inline flag(?s) inline flag
uUnicodeEnables full Unicode matching. Treats the pattern and input as Unicode code points rather than code units.Default in Python 3Default (RE2 engine)Default in regex crate
xExtended / VerboseAllows whitespace and comments in the pattern for readability. Spaces and # comments are ignored.re.VERBOSE(?x) inline flag
yStickyMatches only from the index indicated by the lastIndex property. Does not attempt to match from any later positions.
dHas IndicesGenerates indices for substring matches. Adds an `indices` property to match results with start/end positions.match.span()FindStringIndex()Captures::get()

Ready-to-Use Patterns

Copy-paste regex patterns for the most common tasks. Each pattern is tested, includes examples, and shows usage in multiple languages.

📧

Email Address

Validates a standard email address format.

/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
✓ Matchesuser@example.comjohn.doe+test@sub.domain.org
✗ Non-matchesuser@.com@missing-user.comuser@example
javascript
const regex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
regex.test('user@example.com');
🔗

URL Validation

Validates a web URL including http/https protocols.

/^https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&\/=]*)$/
✓ Matcheshttps://www.example.comhttp://sub.example.co.uk/path?q=1
✗ Non-matcheswww.example.comhttps://htp://example.com
javascript
const regex = /^https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&\/=]*)$/;
regex.test('https://example.com');
🔑

Strong Password

Requires at least 8 characters, one uppercase, one lowercase, one number, and one special character.

/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/
✓ MatchesStrongP@ss1P4ssw0rd!
✗ Non-matchesweakpassOnlyUpper1NoSpecialChar1
javascript
const regex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/;
regex.test('StrongP@ss1');
🖥️

IPv4 Address

Matches a valid IPv4 address (0-255 blocks).

/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
✓ Matches192.168.1.1255.255.255.0
✗ Non-matches256.1.1.1192.168.1192.168.1.1.1
javascript
const regex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
regex.test('192.168.1.1');
🎨

Hex Color Code

Matches 3 or 6 digit hex color codes.

/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/
✓ Matches#FFF#000000#a3f
✗ Non-matches#ZZZ#1234123456
javascript
const regex = /^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/;
regex.test('#FFFFFF');
📅

ISO Date (YYYY-MM-DD)

Matches dates in YYYY-MM-DD format (basic validation).

/^\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])$/
✓ Matches2023-12-251999-01-01
✗ Non-matches2023-13-0123-01-012023/12/25
javascript
const regex = /^\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])$/;
regex.test('2023-12-25');
🏷️

Extract HTML Tags

Matches HTML tags and their attributes.

/<\/?([a-zA-Z0-9]+)(?:\s+[^>]+)?>/g
✓ Matches<div class="test"></div><img>
✗ Non-matches1 < 2Not a tag
javascript
const regex = /<\/?([a-zA-Z0-9]+)(?:\s+[^>]+)?>/g;
const str = '<div>test</div>';
const tags = str.match(regex);
✂️

Trim Whitespace

Matches leading and trailing whitespace to trim it.

/^\s+|\s+$/g
✓ Matches test \twordend\n
✗ Non-matchesno-whitespacemiddle whitespace
javascript
const regex = /^\s+|\s+$/g;
'  test  '.replace(regex, '');

AI Natural Language to Regex

Describe what you want to match in plain English, and our AI will generate the perfect Regular Expression for you.

🔒

Pro Feature Locked

Upgrade to RegexRef Pro to unlock AI Generation, Selection Extraction, and your Personal Library.

Upgrade to Unlock

Text Selection to Regex

Paste a block of text, highlight what you want to extract, and AI will reverse-engineer the regex.

Currently Selected:
No text highlighted yet
🔒

Pro Feature Locked

Upgrade to RegexRef Pro to unlock AI Generation, Selection Extraction, and your Personal Library.

Upgrade to Unlock

Your Personal Library

Save your most frequently used patterns and build your ultimate personal cheat sheet.

Save a Pattern

Saved Patterns

Loading library...
🔒

Pro Feature Locked

Upgrade to RegexRef Pro to unlock AI Generation, Selection Extraction, and your Personal Library.

Upgrade to Unlock

Live Regex Playground

Test your regex patterns in real-time. See matches highlighted, capture groups extracted, and get a plain-English explanation of your pattern.

//gi

Language Reference

See how to use regex in JavaScript, Python, Go, and Rust. Side-by-side code examples for creating, testing, finding, and replacing patterns.

JavaScript.js

Creating Regex
// Using a regex literal
const regex1 = /hello\sworld/gi;

// Using the RegExp constructor
const regex2 = new RegExp('hello\\sworld', 'gi');

// Dynamic pattern from user input
const userInput = 'search term';
const regex3 = new RegExp(
  userInput.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'),
  'g'
);

JavaScript supports regex literals with /pattern/flags syntax and the RegExp constructor for dynamic patterns.

Testing Match
const pattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;

// test() returns boolean
console.log(pattern.test('user@example.com')); // true
console.log(pattern.test('invalid-email'));     // false

// match() returns match details or null
const result = 'user@example.com'.match(pattern);
if (result) {
  console.log(result[0]); // 'user@example.com'
}

Use test() for boolean checks and match() to get match details including captured groups.

Finding All Matches
const text = 'Prices: $9.99, $24.50, and $149.00';
const priceRegex = /\$\d+\.\d{2}/g;

// Using matchAll() - returns iterator of match objects
for (const match of text.matchAll(priceRegex)) {
  console.log(`Found: ${match[0]} at index ${match.index}`);
}

// Using match() with global flag - returns array of matches
const allMatches = text.match(priceRegex);
console.log(allMatches); // ['$9.99', '$24.50', '$149.00']

matchAll() provides detailed match objects with indices, while match() with the g flag returns a simple array of all matches.

Replacing
const text = '2024-01-15';

// Simple replacement
const result1 = text.replace(/-(\d{2})-(\d{2})$/, '/$1/$2');
console.log(result1); // '2024/01/15'

// Using a replacement function
const result2 = 'hello world'.replace(
  /\b\w/g,
  (char) => char.toUpperCase()
);
console.log(result2); // 'Hello World'

// replaceAll() for global replacement
const result3 = 'a.b.c'.replaceAll('.', '-');
console.log(result3); // 'a-b-c'

replace() and replaceAll() support string patterns, regex patterns, and replacement functions for complex transformations.

Named Capture Groups
const dateRegex = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const match = '2024-01-15'.match(dateRegex);

if (match?.groups) {
  const { year, month, day } = match.groups;
  console.log(`Year: ${year}, Month: ${month}, Day: ${day}`);
  // Year: 2024, Month: 01, Day: 15
}

// Named groups in replace()
const reformatted = '2024-01-15'.replace(
  /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/,
  '$<month>/$<day>/$<year>'
);
console.log(reformatted); // '01/15/2024'

Named capture groups use (?<name>...) syntax and are accessible via match.groups object or $<name> in replacement strings.

Python.py

Creating Regex
import re

# Compile a pattern (recommended for reuse)
pattern = re.compile(r'hello\sworld', re.IGNORECASE)

# Use raw strings to avoid escaping backslashes
email_re = re.compile(
    r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
)

# Verbose mode for complex patterns
phone_re = re.compile(r'''
    (?:\+1[-.\ ]?)?     # optional country code
    \(?\d{3}\)?        # area code
    [-.\ ]?             # separator
    \d{3}[-.\ ]?\d{4}  # number
''', re.VERBOSE)

Python uses the re module with compiled patterns for performance. Raw strings (r"...") prevent backslash escaping issues.

Testing Match
import re

pattern = re.compile(r'^\d{4}-\d{2}-\d{2}$')

# search() finds first match anywhere in string
result = re.search(r'\d+', 'abc 123 def')
if result:
    print(result.group())  # '123'
    print(result.span())   # (4, 7)

# match() only matches at beginning of string
result = re.match(r'\d+', '123 abc')
print(bool(result))  # True

# fullmatch() requires entire string to match
result = re.fullmatch(r'\d+', '12345')
print(bool(result))  # True

search() finds matches anywhere, match() only at the start, and fullmatch() requires the entire string to match the pattern.

Finding All Matches
import re

text = 'Prices: $9.99, $24.50, and $149.00'

# findall() returns list of matched strings
prices = re.findall(r'\$\d+\.\d{2}', text)
print(prices)  # ['$9.99', '$24.50', '$149.00']

# finditer() returns iterator of Match objects
for match in re.finditer(r'\$([\d.]+)', text):
    print(f'Found: {match.group(0)} '
          f'(amount: {match.group(1)}) '
          f'at {match.start()}')

findall() returns simple string matches, while finditer() provides full Match objects with groups, spans, and positions.

Replacing
import re

# Simple replacement
result = re.sub(r'\s+', '-', 'hello   world   python')
print(result)  # 'hello-world-python'

# Using backreferences
result = re.sub(r'(\w+) (\w+)', r'\2 \1', 'Hello World')
print(result)  # 'World Hello'

# Using a replacement function
def capitalize(match):
    return match.group(0).upper()

result = re.sub(r'\b[a-z]', capitalize, 'hello world')
print(result)  # 'Hello World'

# subn() also returns the count of replacements
result, count = re.subn(r'\d', '#', 'a1b2c3')
print(f'{result} ({count} replacements)')
# 'a#b#c# (3 replacements)'

re.sub() supports string replacements with backreferences, callable replacements, and subn() returns the replacement count.

Named Capture Groups
import re

pattern = re.compile(
    r'(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})'
)
match = pattern.search('Date: 2024-01-15')

if match:
    print(match.group('year'))   # '2024'
    print(match.group('month'))  # '01'
    print(match.group('day'))    # '15'
    print(match.groupdict())
    # {'year': '2024', 'month': '01', 'day': '15'}

# Named groups in substitution
result = pattern.sub(
    r'\g<month>/\g<day>/\g<year>',
    '2024-01-15'
)
print(result)  # '01/15/2024'

Python uses (?P<name>...) syntax for named groups. Access via group("name") or groupdict(). Use \g<name> in replacements.

Go.go

Creating Regex
package main

import (
    "fmt"
    "regexp"
)

func main() {
    // MustCompile panics on invalid pattern (use at init)
    re := regexp.MustCompile(`\d{4}-\d{2}-\d{2}`)

    // Compile returns an error for invalid patterns
    re2, err := regexp.Compile(`[a-z]+`)
    if err != nil {
        fmt.Println("Invalid pattern:", err)
        return
    }

    // POSIX mode uses leftmost-longest matching
    rePosix := regexp.MustCompilePOSIX(`[a-z]+`)

    fmt.Println(re, re2, rePosix)
}

Go uses the regexp package with RE2 syntax (no backreferences or lookaheads). MustCompile panics on error, Compile returns it.

Testing Match
package main

import (
    "fmt"
    "regexp"
)

func main() {
    re := regexp.MustCompile(`^\d{3}-\d{2}-\d{4}$`)

    // MatchString tests if string matches
    fmt.Println(re.MatchString("123-45-6789")) // true
    fmt.Println(re.MatchString("invalid"))      // false

    // FindString returns the first match
    re2 := regexp.MustCompile(`\d+`)
    fmt.Println(re2.FindString("abc 123 def 456")) // "123"

    // FindStringIndex returns match position
    loc := re2.FindStringIndex("abc 123")
    fmt.Println(loc) // [4 7]
}

MatchString() for boolean checks, FindString() for first match, FindStringIndex() for match positions.

Finding All Matches
package main

import (
    "fmt"
    "regexp"
)

func main() {
    text := "Prices: $9.99, $24.50, and $149.00"
    re := regexp.MustCompile(`\$[\d.]+`)

    // FindAllString returns all matches (-1 = no limit)
    matches := re.FindAllString(text, -1)
    fmt.Println(matches) // [$9.99 $24.50 $149.00]

    // FindAllStringIndex returns positions
    indices := re.FindAllStringIndex(text, -1)
    for _, idx := range indices {
        fmt.Printf("Match at [%d:%d]: %s\n",
            idx[0], idx[1], text[idx[0]:idx[1]])
    }

    // Limit number of matches
    first2 := re.FindAllString(text, 2)
    fmt.Println(first2) // [$9.99 $24.50]
}

FindAllString() retrieves all matches with an optional count limit. Use -1 for no limit. Index variants return match positions.

Replacing
package main

import (
    "fmt"
    "regexp"
    "strings"
)

func main() {
    re := regexp.MustCompile(`\s+`)

    // ReplaceAllString for simple replacements
    result := re.ReplaceAllString("hello   world   go", "-")
    fmt.Println(result) // "hello-world-go"

    // ReplaceAllStringFunc for dynamic replacements
    re2 := regexp.MustCompile(`\b[a-z]`)
    result2 := re2.ReplaceAllStringFunc(
        "hello world", strings.ToUpper,
    )
    fmt.Println(result2) // "Hello World"

    // Using $1 group references
    re3 := regexp.MustCompile(`(\w+)\s(\w+)`)
    result3 := re3.ReplaceAllString(
        "Hello World", "${2} ${1}",
    )
    fmt.Println(result3) // "World Hello"
}

ReplaceAllString() handles simple replacements, ReplaceAllStringFunc() for dynamic transformations, and ${n} for group references.

Named Capture Groups
package main

import (
    "fmt"
    "regexp"
)

func main() {
    re := regexp.MustCompile(
        `(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})`,
    )
    match := re.FindStringSubmatch("Date: 2024-01-15")
    names := re.SubexpNames()

    if len(match) > 0 {
        for i, name := range names {
            if name != "" {
                fmt.Printf("%s: %s\n", name, match[i])
            }
        }
        // year: 2024
        // month: 01
        // day: 15
    }

    // Build a map of named groups
    result := make(map[string]string)
    for i, name := range names {
        if i != 0 && name != "" {
            result[name] = match[i]
        }
    }
    fmt.Println(result) // map[day:15 month:01 year:2024]
}

Go uses (?P<name>...) syntax. Access named groups via SubexpNames() combined with FindStringSubmatch() results.

Rust.rs

Creating Regex
use regex::Regex;
use std::sync::LazyLock;

// Compile at runtime
let re = Regex::new(r"\d{4}-\d{2}-\d{2}").unwrap();

// Compile once with LazyLock for reuse (static lifetime)
static EMAIL_RE: LazyLock<Regex> = LazyLock::new(|| {
    Regex::new(
        r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
    ).unwrap()
});

// Handle compilation errors
match Regex::new(r"[invalid") {
    Ok(re) => println!("Valid: {}", re),
    Err(e) => println!("Error: {}", e),
}

Rust uses the regex crate. Regex::new() returns a Result. Use LazyLock for static patterns. Raw strings r"..." avoid escaping.

Testing Match
use regex::Regex;

fn main() {
    let re = Regex::new(r"^\d{3}-\d{2}-\d{4}$").unwrap();

    // is_match() for boolean checks
    println!("{}", re.is_match("123-45-6789")); // true
    println!("{}", re.is_match("invalid"));      // false

    // find() returns the first Match
    let re2 = Regex::new(r"\d+").unwrap();
    if let Some(m) = re2.find("abc 123 def 456") {
        println!(
            "Found: {} at {}..{}",
            m.as_str(), m.start(), m.end()
        );
        // Found: 123 at 4..7
    }
}

is_match() for boolean tests, find() returns an Option<Match> with the matched text and byte positions.

Finding All Matches
use regex::Regex;

fn main() {
    let text = "Prices: $9.99, $24.50, and $149.00";
    let re = Regex::new(r"\$[\d.]+").unwrap();

    // find_iter() returns iterator of Match objects
    for m in re.find_iter(text) {
        println!(
            "Found: {} at {}..{}",
            m.as_str(), m.start(), m.end()
        );
    }

    // Collect into a Vec
    let matches: Vec<&str> = re
        .find_iter(text)
        .map(|m| m.as_str())
        .collect();
    println!("{:?}", matches);
    // ["$9.99", "$24.50", "$149.00"]

    // captures_iter() for groups
    let re2 = Regex::new(r"\$(\d+)\.(\d{2})").unwrap();
    for cap in re2.captures_iter(text) {
        println!("Dollars: {}, Cents: {}", &cap[1], &cap[2]);
    }
}

find_iter() yields Match objects, captures_iter() yields Captures for accessing groups. Collect into Vec for storage.

Replacing
use regex::Regex;

fn main() {
    let re = Regex::new(r"\s+").unwrap();

    // replace_all() replaces all occurrences
    let result = re.replace_all(
        "hello   world   rust", "-"
    );
    println!("{}", result); // "hello-world-rust"

    // Using capture group references
    let re2 = Regex::new(r"(\w+)\s(\w+)").unwrap();
    let result2 = re2.replace("Hello World", "$2 $1");
    println!("{}", result2); // "World Hello"

    // Using a closure for dynamic replacement
    let re3 = Regex::new(r"\b[a-z]").unwrap();
    let result3 = re3.replace_all(
        "hello world",
        |caps: &regex::Captures| {
            caps[0].to_uppercase()
        }
    );
    println!("{}", result3); // "Hello World"
}

replace() handles first match, replace_all() handles all. Supports $n group references and closure-based dynamic replacements.

Named Capture Groups
use regex::Regex;

fn main() {
    let re = Regex::new(
        r"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})"
    ).unwrap();

    if let Some(caps) = re.captures("Date: 2024-01-15") {
        println!("Year: {}",  &caps["year"]);  // 2024
        println!("Month: {}", &caps["month"]); // 01
        println!("Day: {}",   &caps["day"]);   // 15

        // Access by name or by index
        println!("Full: {}",  &caps[0]); // 2024-01-15
    }

    // Named groups in replacement
    let result = re.replace(
        "2024-01-15", "$month/$day/$year"
    );
    println!("{}", result); // "01/15/2024"
}

Rust uses (?P<name>...) syntax. Access named groups via &caps["name"] or by index. Use $name in replacement strings.

Frequently Asked Questions

Common questions about regular expressions and how to use them.

What is a regular expression (regex)?

A regular expression (regex) is a sequence of characters that specifies a search pattern. They are used by string-searching algorithms for "find" or "find and replace" operations on text, and for input validation.

How do I validate an email address with regex?

While complex email validation is usually best done by sending a verification link, a common basic regex for validating emails is: ^[^\s@]+@[^\s@]+\.[^\s@]+$

What is the difference between a positive lookahead and a negative lookahead?

A positive lookahead (?=...) asserts that a given pattern MUST follow the current position. A negative lookahead (?!...) asserts that a given pattern MUST NOT follow the current position. Neither consumes characters in the final match.

How do I test regular expressions online?

You can use the RegexRef Interactive Playground to test your regex against custom text in real-time. It provides immediate highlighting and match evaluation.