Step-by-Step Evaluation Workflow
Define Expression and Flags
Input your regular expression pattern between the delimiters /.../ and configure required modifiers such as global (g), case-insensitive (i), multiline (m), dotAll (s), Unicode (u), or indices (d).
Supply Target Input Text
Paste, type, or drag and drop log payloads, code snippets, or configuration files into the Test String panel to initiate immediate evaluation.
Inspect Token Matches and Groups
Examine color-coded inline highlights alongside exact character offsets, capture group values, and named capture group dictionaries in the inspector panel.
Test Substitutions and Export Code
Verify replacement strings using reference tokens ($1, $&, $<name>) and export production-ready syntax snippets for JavaScript, Python, Go, PHP, or Java.
Production Pattern Blueprints
Battle-tested expressions with named capture groups for parsing, validation, and data extraction:
1. RFC 5322 Email Extraction
Flags: /gIsolates recipient mailbox into <user> and host into <domain>, supporting subdomains and tags (+v2).
/(?<user>[a-zA-Z0-9._%+-]+)@(?<domain>[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/gOperations: ops@codekivo.com, triage: bug-report+v2@sub.cluster.internal2. RFC 3986 URI & Endpoint Deconstruction
Flags: /gDeconstructs web addresses into distinct named components: host authority, optional port number, resource route path, and raw query string.
/https?:\/\/(?<host>[a-zA-Z0-9.-]+)(?::(?<port>\d+))?(?<path>\/[^\s?#]*)?(?:\?(?<query>[^\s#]*))?/gEndpoint: https://api.service.internal:8443/v2/metrics?filter=active&limit=503. ISO 8601 Timestamp with Timezone Offset
Flags: /gMatches UTC Zulu notations (Z) and explicit directional hour offsets (+02:00) across high-throughput log streams.
/(?<timestamp>\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?(?:Z|[+-]\d{2}:?\d{2}))/g2026-09-16T17:55:00.124Z [INFO] Service worker heartbeat ack at 2026-09-16T18:00:00+02:004. SemVer 2.0.0 Release Specification
AnchoredEnforces positive integer versions without leading zeroes while parsing optional prerelease channel identifiers and build metadata.
/^v?(?<major>0|[1-9]\d*)\.(?<minor>0|[1-9]\d*)\.(?<patch>0|[1-9]\d*)(?:-(?<prerelease>[0-9A-Za-z.-]+))?(?:\+(?<build>[0-9A-Za-z.-]+))?$/v2.14.0-rc.3+build.892JavaScript (ECMAScript) Regex Flags Reference
Modifiers change how the regular expression engine steps through input memory and matches boundaries:
| Flag | Identifier | Engine Behavior & Execution Characteristics |
|---|---|---|
| g | Global | Iterates across the entire string buffer. The engine mutates the lastIndex property on the RegExp instance after each match instead of halting at index 0. |
| i | Ignore Case | Enforces case-folding character comparison. Both ASCII and Unicode character sets match irrespective of casing variations without duplicating uppercase and lowercase ranges. |
| m | Multiline | Alters line boundary anchors: ^ matches line starts (\n or \r) and $ matches line ends, rather than strictly matching the entire buffer boundaries. |
| s | DotAll | Expands wildcard dot (.) semantics to match newline and carriage return characters (\n, \r, \u2028, \u2029). |
| u | Unicode | Processes the pattern as a sequence of 32-bit Unicode code points. Correctly navigates UTF-16 surrogate pairs (e.g. emoji and mathematical symbols) and activates \p{Property} escapes. |
| y | Sticky | Restricts pattern matching to start precisely at the offset specified by lastIndex. Does not scan subsequent characters if the match fails at that exact index. |
| d | Indices | Generates start and end offset index arrays (match.indices) for the complete pattern match and every capturing group (ES2022 specification). |
| v | Unicode Sets | Upgrades u flag with character class set operations (intersection &&, subtraction --) and string property support (ES2024). |
Engine Architecture: Traditional NFA vs DFA Matching Paradigms
Browser JavaScript engines execute regular expressions using a Traditional Non-Deterministic Finite Automaton (NFA) engine. Understanding its internal execution model clarifies why certain features exist and where performance cliffs occur:
Expression-Directed Traversal
NFA engines step through the pattern tokens one by one, attempting to match each token against the current character in the target text. If a branch fails, the engine unwinds to the last saved checkpoint and tries alternative paths.
Backtracking State Stack
When encountering greedy quantifiers (*, +) or alternations (|), the engine pushes backtrack positions onto an internal stack. This mechanism allows lookaheads, lookbehinds, and captured backreferences.
DFA Determinism Comparison
In contrast, text-directed DFA engines (like Go's RE2) scan each character once simultaneously across all possible states. While DFAs guarantee strict O(n) linear execution time, they cannot implement lookaround or backreferences.
Catastrophic Backtracking (ReDoS) Anatomy & Safe Refactoring
Regular Expression Denial of Service (ReDoS) occurs when an NFA engine faces nested ambiguous quantifiers combined with an anchor that fails at the end of a long input:
Vulnerable Pathological Pattern
// Exponential complexity: O(2^n)
const badRegex = /^(a+)+$/;
badRegex.test("aaaaaaaaaaaaaaaaaaaaX");For a 20-character string ending in a mismatch (X), the engine must explore 2^20 ≈ 1,048,576 permutations of dividing string slices between outer and inner quantifiers, blocking the main execution thread.
Deterministic Linear Refactoring
// Guaranteed linear complexity: O(n)
const safeRegex = /^a+$/;
safeRegex.test("aaaaaaaaaaaaaaaaaaaaX");By flattening redundant nested quantifiers or making adjacent tokens mutually exclusive (e.g., matching non-delimiter sequences [^:\s]+ rather than arbitrary wildcards .*), the engine eliminates ambiguous branching paths.
The Statefulness Trap: lastIndex Pointer Mutation with Global (/g) Flag
One of the most frequent defects in JavaScript application logic stems from the stateful cursor mutation of RegExp instances compiled with the /g or /y flags:
The Stateful Mutation Bug
Reusing a RegExp instance compiled with the /g flag mutates its internal lastIndex pointer on each successful match:
const ID_REGEX = /^[A-Z]{3}-\d{4}$/g;
function validateId(input) {
return ID_REGEX.test(input);
}
validateId("ABC-1234"); // true (lastIndex mutates to 8)
validateId("ABC-1234"); // false (searches from index 8!)
validateId("ABC-1234"); // true (resets to 0 after failure)Because .test() resumes scanning from the end of the previous match, identical inputs alternate between passing and failing.
Defensive Engineering Solutions
Choose one of these three battle-tested strategies to guarantee idempotent evaluation:
01Omit the /g flag for boolean validation
When checking validity with .test(), avoid the g modifier entirely so lastIndex is never mutated and stays at 0.
02Explicit pointer reset before execution
If global iteration is strictly required across function scopes, explicitly reset the pointer: ID_REGEX.lastIndex = 0; before each invocation.
03Prefer String.prototype.matchAll()
Modern ECMAScript prefers str.matchAll(regex), returning an immutable iterator of matches without altering external state.
Zero-Width Lookaround Assertions: Matching Without Buffer Consumption
Lookarounds verify that text exists (or does not exist) adjacent to the current position without consuming characters or including them in the full match result ($&):
(?=pattern)
Asserts that the subpattern matches immediately after the current position. Frequently used to validate required criteria (e.g. at least one uppercase letter) without moving the match index.
(?!pattern)
Asserts that the subpattern does NOT match ahead. Essential for keyword exclusions (e.g. matching words not ending in .min.js) and boundary guards.
(?<=pattern)
Asserts that the subpattern matches immediately before the current index. Enables extracting values directly following prefixes (e.g. currency amounts after (?<=\$)\d+).
(?<!pattern)
Asserts that the subpattern does NOT match preceding characters. Commonly used to locate unescaped quotes or backslashes: (?<!\\)".
Cross-Engine Flavor Compatibility Matrix
When exporting patterns tested here to backend services, verify language-specific feature boundaries:
| Language / Runtime | Engine Class | Named Groups | Lookaround Support | Atomic Groups / Possessive |
|---|---|---|---|---|
| JavaScript (ECMAScript) | Traditional NFA | (?<name>...) | Full (variable-length lookbehind) | Emulated via lookaround |
Python (re module) | Traditional NFA | (?P<name>...) | Fixed-width lookbehind only | Supported in Python 3.11+ |
Go (regexp package) | DFA / RE2 | (?P<name>...) | Unsupported (DFA linear restriction) | Unsupported |
PHP (preg_* / PCRE2) | PCRE2 NFA | (?<name>...) / (?P<name>...) | Full (bounded variable lookbehind) | (?>...) and ++, *+ |
Java (java.util.regex) | Traditional NFA | (?<name>...) | Obvious maximum length lookbehind | (?>...) and ++, *+ |
Substitution Token Architecture in Replace Mode
When executing string substitutions in the Replace panel, the replacement string interprets dollar-prefixed identifiers as runtime expansion tokens:
| Token | Expansion Value | Practical Application & Example |
|---|---|---|
| $& | Matched Substring | Wraps or decorates matched targets: <mark>$&</mark> highlights words in place. |
| $1, $2..$99 | Numbered Group | Reorders components: ([0-9]{4})-([0-9]{2}) replaced with $2/$1 reformats year-month pairs. |
| $<name> | Named Group | Refactors data with semantic clarity: $<user>@internal.net swaps the domain while preserving the user variable. |
| $` | Preceding Slice | Inserts the entire substring of the input located before the start index of the current match. |
| $' | Following Slice | Inserts the entire substring of the input located after the end index of the current match. |
| $$ | Literal Dollar | Escapes the token prefix to insert a literal $ character into the output without triggering token expansion. |
Frequently Asked Questions
Why does my regex match too much text (greedy vs lazy matching)?
By default, standard quantifiers (*, +, {m,n}) are greedy: they consume as many characters as possible before backtracking to satisfy the rest of the pattern. Appending a question mark makes them lazy (*?, +?, {m,n}?), matching the fewest characters necessary. For example, <.*> matches from the first < to the very last > across an entire line, whereas <.*?> halts at the first closing >.
Why does RegExp.prototype.test() alternate between returning true and false on identical inputs?
When a regular expression has the global (g) or sticky (y) flag, JavaScript makes the RegExp instance stateful by tracking its lastIndex property. Each successful .test() updates lastIndex to the end of that match. The next call searches strictly from lastIndex onwards until it fails, which resets lastIndex back to 0. For boolean validation, either omit the g flag or manually set regex.lastIndex = 0 before calling .test().
How can I prevent Catastrophic Backtracking (ReDoS) when testing complex patterns?
Catastrophic Backtracking occurs when nested or adjacent ambiguous quantifiers (such as (a+)+$ or (.*a)+) encounter a non-matching suffix, forcing the NFA engine into an exponential O(2^n) search space. To prevent this, eliminate nested quantifiers, ensure alternations do not overlap, use specific character class exclusions like [^"\n]+ instead of .*, and position anchor boundaries early.
How do I test regular expressions against multiline strings and line breaks?
Enable the Multiline (m) flag to make ^ and $ match the start and end of each individual line (\n or \r) rather than the entire string buffer. If you also need the wildcard dot (.) to match across line breaks without halting at newlines, enable the DotAll (s) flag. Both flags can be combined simultaneously as /pattern/ms.
How do named capture groups work in pattern matching and string replacement?
Enclose the subpattern in (?<groupName>...). In JavaScript match results, captured values appear on match.groups.groupName. In the Replace mode, reference the captured value using $<groupName>. Named groups keep code resilient because adding, removing, or reordering groups will never break positional numeric references ($1, $2).
What is the operational difference between positive/negative lookahead and lookbehind?
Lookarounds are zero-width assertions: they test whether adjacent text satisfies a subpattern without consuming characters or including them in the matched string ($&). Lookaheads (?=...) and (?!...) verify what follows the current index, while lookbehinds (?<=...) and (?<!...) verify what precedes it. In modern ECMAScript/V8, both fixed-width and variable-length lookbehinds are fully supported.
Why does a regular expression working in this tester fail when ported to Go (Golang)?
This tester runs on modern ECMAScript (V8), a Traditional NFA engine supporting lookaheads, lookbehinds, and backreferences. Go standard library (regexp package) uses Google RE2, a DFA-based engine that enforces guaranteed O(n) linear execution time. RE2 explicitly disallows lookaround assertions (?=...) and backreferences (\1). When porting to Go, restructure patterns using explicit delimiter boundaries or multi-step string logic.
What do the Indices (d) and Unicode (u) flags do in JavaScript?
The d (hasIndices) flag causes the engine to populate match.indices, an array containing exact start and end offset tuples for the full match and each capture group (ES2022). The u (Unicode) flag treats strings as sequences of 32-bit Unicode code points instead of 16-bit code units, enabling proper handling of emoji/astral characters and activating \p{...} property escapes.
