JavaScript Regular Expressions
Learn ECMAScript regular-expression syntax, matching, captures, flags, lookarounds, Unicode modes, dynamic patterns, and stateful matching.
Advanced
Regular expressions are a pattern language built into ECMAScript. They are useful for searching, validating, extracting, and transforming text, but their semantics are precise: metacharacters, quantifiers, captures, flags, Unicode modes, and state all affect the result.
This lesson builds from literal matching to structured patterns, then moves into captures, lookarounds, Unicode properties, `u`/`v`, dynamic patterns, and stateful matching. Treat a regular expression as executable code: make its intent explicit, test its boundaries, and choose ordinary string operations when they communicate the requirement more clearly.
Literal matching
Start with the smallest useful pattern: literal text.
Runnable example
Output
Ready to run.
Quick check
What does `/cat/` match?
Character classes
A character class chooses one code unit or code point from a set or range, depending on the pattern mode. Negated classes use `[^...]`.
Runnable example
Output
Ready to run.
Quick check
Which pattern matches one ASCII digit?
Quantifiers
Quantifiers control how many times the preceding atom may occur. `*`, `+`, `?`, and `{m,n}` express repetition; adding `?` can make a quantifier lazy.
Runnable example
Output
Ready to run.
Quick check
Which quantifier means one or more?
Anchors and boundaries
Anchors constrain where a match can occur. `^` and `$` concern input boundaries, while `\b` and `\B` concern word boundaries.
Runnable example
Output
Ready to run.
Quick check
Which pattern requires the entire string to be exactly `cat`?
Capturing groups
Parentheses group pattern structure and, by default, capture the text matched by the group. Non-capturing groups use `(?:...)` when you need grouping without a capture slot.
Runnable example
Output
Ready to run.
Quick check
What is `match[0]` in a successful `exec()` result?
Named capturing groups
Named groups make captures self-describing with `(?<name>...)`. A successful match exposes them through `match.groups`.
Runnable example
Output
Ready to run.
Quick check
Where are named captures exposed on a successful match?
Alternation and precedence
The `|` operator expresses alternatives. Group it when the alternative is part of a larger structure so precedence is explicit.
Runnable example
Output
Ready to run.
Quick check
Why is `^(cat|dog)$` clearer than `^cat|dog$` for exactly one whole word?
Flags and matching modes
Flags modify matching behavior. Common flags include `i` for case-insensitive matching, `m` for line anchors, `s` for dot-all, `g` for global matching, `u` for Unicode-aware patterns, and `v` for Unicode sets.
Runnable example
Output
Ready to run.
Quick check
Which flag makes `.` also match line terminators?
Match indices with the `d` flag
The `d` flag asks a RegExp to expose the start and end positions of the overall match and each participating capture. The resulting match object has an `indices` property; without `d`, that property is absent. `RegExp.prototype.hasIndices` reports whether the flag was present.
Runnable example
Output
Ready to run.
Quick check
What does the `d` flag add to a successful RegExp match?
Captures get their own ranges
Output
Ready to run.
Quick check
Where is the range for a named capture such as `word` available?
The range pairs are `[start, end]`, with the end position exclusive. The first pair describes the complete match, and subsequent pairs correspond to capturing groups. A capture that did not participate has no range, so its corresponding entry is `undefined`.
Unmatched captures stay undefined
Output
Ready to run.
Quick check
If an alternative capture did not participate, what does its indices entry contain?
`d` works with normal RegExp result-producing methods
Output
Ready to run.
Quick check
What does `/(?<value>\d+)/d.hasIndices` return?
The indices are positions in the matched input, not substrings. This makes `d` useful when later code needs exact source ranges—for example, to annotate, slice, highlight, or map captures back to the original string. The RegExp still returns its normal captured strings; `indices` is additional range information.
Unicode-aware indexing
Output
Ready to run.
Quick check
Why can `/^(.)/d` and `/^(.)/du` report different ranges for the same supplementary character?
Do not confuse these indices with byte offsets. They are positions in the ECMAScript string model, with Unicode-aware matching applying the specification’s code-point-aware conversion where required. The exact range behavior matters when text contains supplementary Unicode characters.
String regex methods
String methods delegate to regular expressions through well-known symbols. `search`, `match`, `matchAll`, `replace`, `replaceAll`, and `split` serve different jobs.
Runnable example
Output
Ready to run.
Quick check
Which method returns an index rather than match text?
Global matches and matchAll
`match()` has different result shapes depending on flags. `matchAll()` provides an iterator of match results and requires a global or sticky pattern.
Runnable example
Output
Ready to run.
Quick check
Why is `g` useful with `matchAll()`?
Lookahead and lookbehind
Lookarounds assert context without consuming that context. Positive and negative lookahead use `(?=...)` and `(?!...)`; lookbehind uses `(?<=...)` and `(?<!...)`.
Runnable example
Output
Ready to run.
Quick check
Which construct checks what follows without consuming it?
Unicode-aware patterns
The `u` flag enables Unicode-aware RegExp semantics. It matters for supplementary code points, Unicode escapes, and character classes.
Runnable example
Output
Ready to run.
Quick check
Which pattern treats the emoji as one Unicode code point for `.`?
Unicode property escapes
Unicode property escapes such as `\p{Letter}` and `\p{Number}` require Unicode mode. They let patterns describe Unicode properties instead of hard-coded ranges.
Runnable example
Output
Ready to run.
Quick check
What does `\p{Letter}` describe in Unicode mode?
Unicode sets with v
The `v` flag enables Unicode sets mode in addition to full Unicode matching. It supports richer character-set operations and string properties defined by the current specification.
Runnable example
Output
Ready to run.
Quick check
Which flag enables Unicode sets mode?
Dot and escapes
The dot is a wildcard for a single input element under the pattern mode, while backslashes introduce escapes such as `\d`, `\s`, and escaped metacharacters. The `s` flag changes dot behavior by allowing line terminators.
Runnable example
Output
Ready to run.
Quick check
Which pattern treats the dot as a literal period?
Dynamic patterns and escaping
Use `new RegExp()` when the pattern must be assembled at runtime. Escape user-provided text before embedding it in a pattern; string escaping and RegExp escaping are separate concerns.
Runnable example
Output
Ready to run.
Quick check
When constructing a pattern from variable text, what must you consider?
Stateful lastIndex
Global and sticky regular expressions can maintain matching state through `lastIndex`. Reusing a stateful RegExp requires deliberate handling.
Runnable example
Output
Ready to run.
Quick check
Why should reusable `/g` or `/y` RegExp objects be treated as stateful?
Designing maintainable regexes
A regex is code: keep it readable, test edge cases, choose the narrowest correct pattern, and avoid using a complex expression where ordinary string logic is clearer.
Runnable example
Output
Ready to run.
Quick check
What is the strongest maintainability rule for a complex pattern?
RegExp.escape() — literal text for a pattern
RegExp.escape() produces RegExp pattern text that treats supplied input as literal content. It handles the escaping rules required when data, rather than hand-written pattern syntax, is inserted into a regular expression.
Output
Ready to run.
Quick check
What problem does RegExp.escape() solve?
const pattern = new RegExp(RegExp.escape("a+b"));
document.querySelector("#output").textContent = String(pattern.test("a+b"));
Inline RegExp modifiers — local flag changes
Inline RegExp modifiers enable or disable selected regular-expression flags for a nested pattern region. They provide local control inside one pattern instead of forcing one flag setting across the entire expression.
Output
Ready to run.
Quick check
What do inline RegExp modifiers control?
try { const pattern = new RegExp('a(?i:b)c'); document.querySelector("#output").textContent = String(pattern.test("aBc")); } catch { document.querySelector("#output").textContent = "Feature unavailable in this runtime."; }
Thanks for your feedback.
Mark this learning resource complete to track your learning progress.