Tags: regex, string-processing, validation, parsing, javascript, python
Level: intermediate
TL;DR: Pattern matching and text processing syntax, anchors, quantifiers, lookarounds, and performance pitfalls.
Metacharacters define syntax: . matches any char except newline, ^ matches start of string, $ matches end.
Character classes group characters: [a-z] matches range, [^0-9] negates range.
Predefined shorthand classes: \d digits, \w word characters, \s whitespace, uppercase variants invert match.
Quantifiers determine repetition: * (0+), + (1+), ? (0 or 1), {n,m} (between n and m).
Quantifiers are greedy by default; append ? (*?, +?) for lazy or non-greedy matching.
Capturing groups (...) store matches; non-capturing groups (?:...) avoid memory overhead.
Named capturing groups (?<name>...) improve readability and simplify extraction.
Lookahead (?=...) and (?!...) assert condition forward without consuming characters.
Lookbehind (?<=...) and (?<!...) assert condition backward without consuming characters.
Common flags: g (global), i (case-insensitive), m (multiline), s (dotAll), u (unicode).
Q: What is the difference between greedy and lazy matching?R: Greedy quantifiers match the longest possible string that satisfies the pattern, whereas lazy quantifiers match the shortest possible string.
Q: How do lookarounds work and when do you use them?R: Lookarounds assert whether a subpattern matches before or after the current position without consuming characters or including them in the match result.
Q: What is catastrophic backtracking and how do you prevent it?R: It occurs when nested ambiguous quantifiers cause exponential combinations on non-matching inputs; I fix it using atomic groups, possessive quantifiers, or strictly disjoint character classes.
Unescaped special characters like . matching any character instead of a literal dot.
Missing ^ and $ when validating whole strings, which allows partial substring matches.
Nested quantifiers such as (a+)+ causing ReDoS through catastrophic backtracking.
Using \w expecting only ASCII letters and digits while ignoring locale or unicode variations.
Using global flag g on stateful JavaScript RegExp.test() causing alternating boolean results across calls.
// Email format check
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
const isValid = emailRegex.test("user@example.com");
// Named capturing groups
const isoDateRegex = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const match = "2026-10-25".match(isoDateRegex);
const year = match?.groups?.year;
// Lookahead assertion (password requires at least one digit)
const passwordRegex = /^(?=.*\d)[A-Za-z\d@$!%*?&]{8,}$/;
// Safe string replace with global flag
const cleanText = "foo bar foo".replace(/foo/g, "baz");
[ ] Construct lookbehind patterns with variable length restrictions across different engines
[ ] Identify and eliminate exponential backtracking in complex input validation patterns
[x] Basic character classes and quantifier syntax