What is a Regular Expression?
A regular expression (shortened to regex or regexp) is a sequence of characters that defines a text search pattern. The concept was formalised in the 1950s by mathematician Stephen Kleene and has been part of computing since the early days of Unix. Today, regex is supported natively in virtually every programming language: JavaScript, Python, PHP, Ruby, Java, Go, Rust, and many more.
Regex is used for: finding whether a string matches a pattern (validation), extracting parts of a string (parsing), replacing text (find-and-replace), splitting strings on complex delimiters, and more. The tradeoff for this power is that regex patterns can be difficult to read without experience.
Literals and Metacharacters
The simplest regex is a literal — a pattern that matches exactly what you type. The pattern hello matches the exact string "hello" wherever it appears in a text.
Metacharacters are special characters with reserved meanings in regex. There are 12 metacharacters you must know:
| Character | Meaning | Example |
|---|---|---|
. | Match any single character (except newline) | c.t matches "cat", "cut", "c3t" |
^ | Match start of string (or line in multiline mode) | ^Hello matches "Hello World" but not "Say Hello" |
$ | Match end of string (or line) | world$ matches "hello world" but not "world hello" |
* | Match 0 or more of the preceding | go* matches "g", "go", "goo", "gooo" |
+ | Match 1 or more of the preceding | go+ matches "go", "goo" but not "g" |
? | Match 0 or 1 of the preceding (optional) | colou?r matches "color" and "colour" |
{} | Match exact or ranged count | a{3} matches "aaa"; a{2,4} matches "aa" to "aaaa" |
[] | Character class (match any one of these) | [aeiou] matches any vowel |
\ | Escape metacharacter or shorthand class | \. matches a literal dot |
| | Alternation (OR) | cat|dog matches "cat" or "dog" |
() | Grouping and capture | (ab)+ matches "ab", "abab", "ababab" |
To match a literal metacharacter, escape it with a backslash. To match a literal dot: \.. To match a literal plus: \+.
Character Classes
Character classes, defined with square brackets [], match any one of the characters inside them:
[abc]— matches "a", "b", or "c"[a-z]— any lowercase letter (range notation)[A-Z]— any uppercase letter[0-9]— any digit[a-zA-Z0-9]— any alphanumeric character[^abc]— any character that is NOT a, b, or c (negation with ^)
Shorthand Character Classes
These built-in shortcuts save you from writing verbose character classes:
\d— digit: equivalent to[0-9]\D— non-digit: equivalent to[^0-9]\w— word character:[a-zA-Z0-9_]\W— non-word character\s— whitespace (space, tab, newline)\S— non-whitespace
Quantifiers
Quantifiers specify how many times the preceding element must occur:
*— zero or more (0+)+— one or more (1+)?— zero or one (optional){n}— exactly n times{n,}— n or more times{n,m}— between n and m times (inclusive)
Greedy vs Lazy
By default, quantifiers are greedy — they match as many characters as possible. Adding a ? after a quantifier makes it lazy — it matches as few characters as possible:
// Input: <b>bold</b> and <i>italic</i>
// Greedy: <.*> matches the ENTIRE string from <b> to </i>
// Lazy: <.*?> matches <b>, then </b>, then <i>, then </i> separately
Anchors
Anchors match positions in a string, not characters:
^— start of the string (or start of line in multiline mode)$— end of the string (or end of line)\b— word boundary (between a word character and a non-word character)\B— non-word boundary
// Match "cat" only as a whole word
\bcat\b // matches "cat" in "the cat sat" but not in "catapult"
// Match email at start of line
^\w+@\w+\.\w+$
Groups and Captures
Parentheses serve two purposes: grouping (applying a quantifier to multiple characters) and capturing (saving the matched text for later use).
// Grouping: match "ab" repeated one or more times
(ab)+ // matches "ab", "abab", "ababab"
// Capturing: extract year, month, day from a date
(\d{4})-(\d{2})-(\d{2})
// Group 1: year, Group 2: month, Group 3: day
In JavaScript, captured groups are accessible via the match() result array. In replacement strings, use $1, $2, etc. to reference captured text.
Non-capturing groups use (?:...) syntax — they group without capturing, which is more efficient when you only need the grouping behavior:
(?:https?|ftp):// // group without capturing the protocol
Named captures (supported in modern JavaScript, Python, and most modern engines) use (?<name>...):
(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})
Lookaheads and Lookbehinds
Lookarounds match based on what precedes or follows the current position, without consuming characters. They are zero-width assertions.
(?=...)— positive lookahead: position is followed by pattern(?!...)— negative lookahead: position is NOT followed by pattern(?<=...)— positive lookbehind: position is preceded by pattern(?<!...)— negative lookbehind: position is NOT preceded by pattern
// Match a number followed by "px" but do not include "px"
\d+(?=px) // matches "12" in "12px"
// Match "file" not followed by ".txt"
file(?!\.txt)
// Match price preceded by "$"
(?<=\$)\d+\.\d{2} // matches "9.99" in "$9.99"
The full reference for JavaScript regex syntax is documented on MDN. For advanced PCRE features, the PCRE documentation is the definitive reference.
Flags
Flags (modifiers) change how the regex engine processes the pattern:
i— case-insensitive:/hello/imatches "Hello", "HELLO", "hElLo"g— global: find all matches, not just the firstm— multiline:^and$match start/end of each lines— dotAll:.matches newline characters toou— Unicode: treat pattern and string as Unicode code pointsy— sticky: match only from lastIndex position
Common Patterns Reference
These patterns cover the most common real-world validation use cases. Note that for production validation — especially email — the definitive validator is attempting to send the email and handling bounces, not a regex pattern.
// Email (simplified, covers 99%+ of real addresses)
^[^\s@]+@[^\s@]+\.[^\s@]+$
// UK phone number
^(\+44|0)[\d\s\-()]{9,13}$
// US phone number (various formats)
^(\+1)?[\s\-.]?\(?\d{3}\)?[\s\-.]?\d{3}[\s\-.]?\d{4}$
// URL (http/https)
^https?:\/\/([\w\-]+\.)+[\w]{2,}(\/[\w\-._~:/?#[\]@!$&'()*+,;=%]*)?$
// Postal code: UK
^[A-Z]{1,2}\d[A-Z\d]?\s?\d[A-Z]{2}$
// Postal code: US ZIP
^\d{5}(-\d{4})?$
// IPv4 address
^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$
// Date: YYYY-MM-DD
^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$
// Hex colour code
^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$
Try It Free — No Signup Required
Test and debug your regex patterns instantly with real-time match highlighting, flag support, and group visualisation.
Open Regex Tester