Master powerful regex patterns used in production systems for search, validation, parsing, and text processing
Regular expressions (regex) are one of the most powerful but misunderstood tools in JavaScript. Basic patterns like /abc/ or \d+ barely scratch the surface. In large-scale applications—search engines, data validators, document parsers, AI-driven text extraction, authentication workflows—advanced regex features determine whether processing is fast, accurate, and maintainable.
💡 Running Code Locally:
While this online editor runs real JavaScript, some advanced examples may have limitations. For the best experience:
.html file with <script> tags and open it in your browserJavaScript uses a backtracking engine, which tries different paths until it finds a match or fails. Understanding this behaviour is essential to writing patterns that don't freeze the browser.
Understanding dangerous regex patterns that can freeze your browser
const pattern = /(a+)+b/;
// This pattern is notorious — it can cause catastrophic backtracking
// with long strings of 'a' characters without a 'b'
pattern.test("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
// The engine tries every possible grouping of a's
// before realizing there's no 'b' to matchLookarounds match conditions without consuming characters, enabling ultra-flexible logic.
Match patterns only if followed by specific characters
// Match "user" only if followed by a number
const pattern = /user(?=\d+)/;
console.log(pattern.test("user123")); // true
console.log(pattern.test("username")); // false
// The lookahead (?=\d+) checks but doesn't consumeMatch patterns only if NOT followed by specific characters
// Match "user" only if NOT followed by a number
const pattern = /user(?!\d)/;
console.log(pattern.test("username")); // true
console.log(pattern.test("user123")); // falseMatch patterns only if preceded by specific characters
// Match digits that follow a £ sign
const price = /(?<=£)\d+/g;
console.log("£120 cost".match(price)); // ["120"]
console.log("$120 cost".match(price)); // nullMatch patterns only if NOT preceded by specific characters
// Match numbers NOT preceded by a £
const pattern = /(?<!£)\d+/g;
console.log("£120 and 50 items".match(pattern)); // ["50"]Named groups make regex readable and maintainable.
Use named groups for readable and maintainable regex
const pattern = /(?<day>\d{2})-(?<month>\d{2})-(?<year>\d{4})/;
const m = pattern.exec("12-11-2025");
console.log(m.groups.day); // "12"
console.log(m.groups.month); // "11"
console.log(m.groups.year); // "2025"
// Much cleaner than m[1], m[2], m[3]!Reference captured groups by name to match repeated patterns
// Match repeated words like "hello hello"
const dup = /(?<word>\b\w+\b) \k<word>/;
console.log(dup.test("hello hello")); // true
console.log(dup.test("hello world")); // false
// \k<word> references the named captureJavaScript regex with the u flag unlocks global text matching.
Match emoji, accented characters, and international text
// Match emoji
const emoji = /\p{Emoji}/u;
console.log(emoji.test("🎉")); // true
// Match any letter across all languages
const letters = /\p{Letter}+/gu;
console.log("Héllo Wörld 日本語".match(letters));
// ["Héllo", "Wörld", "日本語"]
// Normalize accents
const normalized = "café".normalize("NFD").replace(/\p{Diacritic}/gu, "");
console.log(normalized); // "cafe"See how greedy quantifiers expand to match as much as possible
// Greedy — expands as much as possible
const greedy = /<.*>/;
console.log("<div>Hello</div>".match(greedy));
// ["<div>Hello</div>"] — matches EVERYTHINGSee how lazy quantifiers match the smallest possible string
// Lazy — smallest match
const lazy = /<.*?>/;
console.log("<div>Hello</div>".match(lazy));
// ["<div>"] — stops at first >
// Use lazy quantifiers for matching tags, code blocks, delimited structuresPrevent catastrophic backtracking with atomic-like patterns
// JavaScript doesn't support *+ directly
// Simulate atomic groups using lookahead + reference
// Catastrophic pattern:
const dangerous = /(a+)+b/;
// Safer atomic simulation:
const atomic = /(?=(a+))\1b/;
// The lookahead locks in the match length
// Backtracking becomes impossibleExtract key-value pairs from HTML using named capture groups
const attr = /\b(?<key>[a-zA-Z-]+)\s*=\s*"(?<value>[^"]*)"/g;
const html = '<img src="image.png" alt="photo" width="200">';
for (const match of html.matchAll(attr)) {
console.log(`${match.groups.key}: ${match.groups.value}`);
}
// src: image.png
// alt: photo
// width: 200
// Perfect for HTML sanitation, browser automation, code editorsRegex can simulate a tokenizer without a parser.
Parse code into tokens using regex with named groups
const tokenizer = /(?<number>\d+)|(?<word>[A-Za-z]+)|(?<symbol>[^A-Za-z0-9\s])/g;
const input = "var x = 42;";
for (const match of input.matchAll(tokenizer)) {
const type = Object.keys(match.groups).find(k => match.groups[k]);
console.log(`${type}: ${match[0]}`);
}
// word: var
// word: x
// symbol: =
// number: 42
// symbol: ;
// Useful for mini interpreters, syntax highlighters, command parsingHard-coded patterns don't scale. Build regexes dynamically for large systems.
Build regex patterns dynamically from arrays of keywords
function buildFilter(words) {
// Escape special regex characters
const escaped = words.map(w =>
w.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
);
return new RegExp(`\\b(${escaped.join("|")})\\b`, "gi");
}
const banned = buildFilter(["spam", "ads", "scam"]);
console.log(banned.test("This is spam content")); // true
console.log(banned.test("This is clean content")); // false
// Useful for moderation tools, custom filters, keyword enginesRegex that works for 10 strings may fail catastrophically on 10 million.
Techniques to write fast and efficient regex patterns
// 1. Avoid backtracking bombs
// ❌ Dangerous
const bad = /(.+)+/;
// ✔ Safe
const good = /^.+$/;
// 2. Prefer character classes over alternatives
// ❌ Slow
const slow = /(a|b|c|d)/;
// ✔ Fast
const fast = /[abcd]/;
// 3. Avoid .* when possible — use specific classes
// ❌ Greedy and slow
const vague = /start.*end/;
// ✔ More specific
const precise = /start[^e]*end/;
// 4. Precompile regex objects
const emailRegex = /^[^@\s]+@[^@\s]+\.[^@\s]+$/;
// 5. Break giant patterns into stages
const
...Regex patterns for sanitization and input validation
// Block script injections
function stripScripts(html) {
return html.replace(/<script[\s\S]*?>[\s\S]*?<\/script>/gi, "");
}
// Validate safe filenames
const safeFilename = /^[A-Za-z0-9_\-.]+$/;
// Validate URL
const urlPattern = /https?:\/\/[^\s/$.?#].[^\s]*/i;
// Escape user input before using in regex
function escapeRegex(str) {
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
// Example: safe search
const userSearch = escapeRegex(userInput);
const searchPattern = new RegExp(userSe
...Common regex patterns every developer should know
// Detect duplicate words
const duplicates = /\b(\w+)\s+\1\b/gi;
console.log("hello hello world".match(duplicates)); // ["hello hello"]
// Validate complex date formats
const datePattern = /^(0[1-9]|[12]\d|3[01])-(0[1-9]|1[0-2])-\d{4}$/;
// Extract function names from JS
const funcNames = /(?<=function\s+)[A-Za-z_]\w*/g;
console.log("function hello() {} function world() {}".match(funcNames));
// ["hello", "world"]
// Match HTML entities
const entities = /&[a-z]+;/gi;
// Extract everything in
...Sign up for free to track which lessons you've completed and get learning reminders.