Regex Tester

Test regular expressions with live highlighting, capture groups, and explanations.

Free Online Regex Tester

Regular expressions power validation, parsing, and search across every language. Dokall's regex playground lets you type a pattern, toggle flags, and see matches highlighted instantly - with capture groups and basic token explanations.

Use preset patterns for email, URL, phone numbers, dates, and more, or build your own. Everything runs in your browser - no data sent to a server.

What is a Regular Expression?

A regular expression (regex) is a pattern that describes a set of strings. It is used for searching, matching, extracting, and replacing text. Nearly every programming language, text editor, and command-line tool supports regex in some form.

A simple regex like [0-9]{3}-[0-9]{4} matches phone number fragments like 555-1234. A more complex pattern can validate email formats, parse log files, extract URLs from HTML, or find and replace across thousands of files. Learning regex pays off quickly because it is a universal skill that transfers across languages and tools.

Regex Syntax Quick Reference

Literal characters match themselves: abc matches the string "abc". Dot . matches any single character except newline. Backslash \ escapes special characters: \. matches a literal dot.

Character classes define sets: [aeiou] matches any vowel, [0-9] matches any digit, [^0-9] matches any non-digit. Shorthand classes save typing: \d for digits, \w for word characters (letters, digits, underscore), \s for whitespace.

Anchors match positions, not characters: ^ matches the start of a line, $ matches the end. \b matches a word boundary - useful for matching whole words without partial matches.

Alternation uses the pipe: cat|dog matches either "cat" or "dog". Use parentheses to group alternations: (cat|dog) food matches "cat food" or "dog food".

Quantifiers: How Many Times to Match

Quantifiers specify repetition. * means zero or more, + means one or more, ? means zero or one. {n} means exactly n times, {n,} means n or more, {n,m} means between n and m times.

By default, quantifiers are greedy - they match as much as possible. The pattern ".*" applied to "hello" "world" matches the entire string including both quotes. Adding ? makes them lazy: ".*?" matches just "hello".

This greedy vs lazy distinction is one of the most common sources of regex bugs. When your pattern matches more than expected, try switching to a lazy quantifier or using a negated character class like [^"]* instead of .*.

Capture Groups and Backreferences

Parentheses create capture groups that let you extract parts of a match. The pattern (\d{4})-(\d{2})-(\d{2}) applied to "2024-01-15" captures "2024" in group 1, "01" in group 2, and "15" in group 3.

In replacement strings, you can reference captured groups: replacing (\w+)@(\w+) with $1 at $2 turns "user@host" into "user at host". Backreferences within the pattern itself use \1, \2, etc.: (\w+)\s+\1 matches repeated words like "the the".

Non-capturing groups (?:...) group without capturing. Use them when you need grouping for alternation or quantifiers but do not need to extract the matched text. They are slightly faster because the engine does not need to store the match.

Lookaheads and Lookbehinds

Lookaheads and lookbehinds (collectively called lookarounds) assert that a pattern exists before or after the current position without including it in the match.

Positive lookahead (?=...) matches if the pattern ahead exists: \d+(?= dollars) matches "100" in "100 dollars" but not in "100 euros". Negative lookahead (?!...) matches if the pattern ahead does not exist: \d+(?! dollars) matches "100" in "100 euros".

Positive lookbehind (?<=...) matches if the pattern behind exists: (?<=\$)\d+ matches "50" in "$50". Negative lookbehind (?<!...) excludes: (?<!\$)\d+ matches "50" when it is not preceded by a dollar sign.

Lookarounds are zero-width - they check a condition without consuming characters. This makes them powerful for complex matching rules without altering what gets captured or replaced.

Common Regex Patterns

Email (basic): [a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,} - matches most common email formats. For production validation, use your language's email library instead of regex.

URL: https?://[^\s]+ - matches HTTP and HTTPS URLs. For strict URL validation, the pattern gets significantly more complex.

IPv4 address: \b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b - matches four dot-separated number groups. Does not validate that each octet is 0-255.

ISO date: \d{4}-\d{2}-\d{2} - matches YYYY-MM-DD format. Does not validate month/day ranges.

Strong password check: ^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^a-zA-Z\d]).{8,}$ - requires at least one lowercase, one uppercase, one digit, one special character, and minimum 8 characters. Uses multiple lookaheads.

Regex Performance: Avoiding Catastrophic Backtracking

The regex engine tries every possible way to match a pattern. Some patterns cause exponential backtracking - the engine explores a huge number of paths before failing. This can freeze your application.

The classic example is (a+)+ applied to a string of a's followed by a non-matching character. The engine tries every way to split the a's between the inner and outer groups before concluding there is no match. With 25 a's, this can take billions of steps.

To avoid catastrophic backtracking: use atomic groups (?>...) or possessive quantifiers a++ when your engine supports them, prefer specific character classes over .*, avoid nested quantifiers like (a+)+, and test your patterns with long non-matching inputs. If a pattern takes more than a few milliseconds, it is likely vulnerable.

Frequently Asked Questions

What does regex stand for?
Regex is short for regular expression. The term comes from formal language theory in computer science, where regular expressions describe regular languages. In practice, modern regex engines support features (backreferences, lookarounds) that go beyond the formal definition.
How do I match an email address with regex?
A common pattern is [a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}. This matches most standard email formats. However, the full email spec (RFC 5322) allows quoted strings, comments, and other edge cases that no simple regex can handle. For production use, validate the format loosely with regex and confirm delivery by sending a verification email.
What is the difference between * and + in regex?
* matches zero or more occurrences of the preceding element. + matches one or more. For example, a* matches "" (empty string), "a", "aa", "aaa", etc. a+ matches "a", "aa", "aaa" but not an empty string. Use + when you require at least one match.
What are regex flags?
Flags modify how the pattern is applied. Common flags: g (global) finds all matches instead of stopping at the first. i (case-insensitive) makes [a-z] also match uppercase letters. m (multiline) makes ^ and $ match the start and end of each line, not just the entire string. s (dotAll) makes . match newline characters. u (unicode) enables full Unicode matching.
What is a non-capturing group?
A non-capturing group (?:...) groups elements for alternation or quantifiers without storing the matched text. Regular groups () capture the match into numbered references ($1, $2). Use non-capturing groups when you need grouping but do not need the captured value - they are slightly more efficient.
Why is my regex slow (catastrophic backtracking)?
Catastrophic backtracking happens when a pattern has nested quantifiers or overlapping alternatives that create exponentially many matching paths. Example: (a+)+ on a long non-matching string. The engine tries every possible way to split the input before failing. Fix by using possessive quantifiers (a++), atomic groups, or restructuring the pattern to eliminate ambiguity.
How do I escape special characters in regex?
Prepend a backslash: \. matches a literal dot, \[ matches a literal bracket, \\ matches a literal backslash. Special characters that need escaping: . * + ? ^ $ { } [ ] ( ) | \. Inside a character class [...], most characters are literal - only ], \, ^, and - need escaping.
What is the difference between greedy and lazy matching?
Greedy quantifiers (*, +, {n,}) match as much text as possible. Lazy quantifiers (*?, +?, {n,}?) match as little as possible. Example: given the string "<b>bold</b>", the pattern <.*> (greedy) matches the entire string, while <.*?> (lazy) matches just "<b>". Use lazy matching when you want the shortest possible match.