Regular Expressions Reference
A comprehensive reference for JavaScript/TypeScript regular expressions — syntax, flags, methods, and real-world patterns commonly used in React applications.
Event Reference
| Method | Returns | Description |
|---|---|---|
regex.test(str) | boolean | Returns true if the pattern matches anywhere in the string |
regex.exec(str) | RegExpExecArray | null | Returns match details (groups, index) or null |
str.match(regex) | RegExpMatchArray | null | Returns matches — behavior changes with g flag |
str.matchAll(regex) | IterableIterator<RegExpMatchArray> | Returns iterator of all matches (requires g flag) |
str.search(regex) | number | Returns index of first match, or -1 |
str.replace(regex, replacement) | string | Replaces first match (or all with g flag) |
str.replaceAll(regex, replacement) | string | Replaces all matches (requires g flag) |
str.split(regex) | string[] | Splits string by regex matches |
Recipe
Quick-reference — most common regex operations in TypeScript.
// Test if a string matches
const isEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test("user@example.com"); // true
// Extract matches
const matches = "2024-01-15".match(/(\d{4})-(\d{2})-(\d{2})/);
// matches[1] = "2024", matches[2] = "01", matches[3] = "15"
// Named capture groups
const result = "2024-01-15".match(/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/);
// result?.groups?.year = "2024"
// Replace with pattern
const slug = "Hello World! Foo".replace(/[^a-zA-Z0-9]+/g, "-").toLowerCase();
// "hello-world-foo"
// Split by pattern
const words = "one, two; three".split(/[,;]\s*/);
// ["one", "two", "three"]When to reach for this: Input validation, text parsing, URL routing, search/filter logic, and data transformation in forms and utilities.
Working Example
"use client";
import { useState } from "react";
interface ValidationResult {
field: string;
value: string;
isValid: boolean;
message: string;
}
const VALIDATORS: Record<string, { pattern: RegExp; message: string }> = {
email: {
pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
message: "Must be a valid email address",
},
phone: {
pattern: /^\+?[\d\s\-()]{7,15}$/,
message: "Must be a valid phone number (7-15 digits)",
},
url: {
pattern: /^https?:\/\/[^\s/$.?#].[^\s]*$/i,
message: "Must be a valid URL starting with http(s)://",
},
zipCode: {
pattern: /^\d{5}(-\d{4})?$/,
message: "Must be a valid US zip code (12345 or 12345-6789)",
},
password: {
pattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*]).{8,}$/,
message: "Min 8 chars, 1 uppercase, 1 lowercase, 1 digit, 1 special char",
},
};
export default function RegexValidationDemo() {
const [results, setResults] = useState<ValidationResult[]>([]);
const [input, setInput] = useState("");
const [selected, setSelected] = useState("email");
function validate() {
const { pattern, message } = VALIDATORS[selected];
const isValid = pattern.test(input);
setResults((prev) => [
{ field: selected, value: input, isValid, message: isValid ? "Valid" : message },
...prev,
]);
}
return (
<div className="space-y-4 p-4 max-w-md">
<select
value={selected}
onChange={(e) => setSelected(e.target.value)}
className="border rounded px-2 py-1 w-full"
>
{Object.keys(VALIDATORS).map((key) => (
<option key={key} value={key}>{key}</option>
))}
</select>
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder={`Enter ${selected}...`}
className="border rounded px-2 py-1 w-full"
/>
<button onClick={validate} className="bg-blue-600 text-white px-4 py-1 rounded">
Validate
</button>
<ul className="space-y-1 text-sm">
{results.map((r, i) => (
<li key={i} className={r.isValid ? "text-green-600" : "text-red-600"}>
<strong>{r.field}:</strong> "{r.value}" — {r.message}
</li>
))}
</ul>
</div>
);
}What this demonstrates:
- Using
RegExp.test()for boolean validation - Storing regex patterns in a typed lookup object
- Common real-world validation patterns (email, phone, URL, zip, password)
Deep Dive
Regex Syntax Reference
Character Classes
// Predefined
/\d/ // Digit [0-9]
/\D/ // Non-digit [^0-9]
/\w/ // Word char [a-zA-Z0-9_]
/\W/ // Non-word char
/\s/ // Whitespace (space, tab, newline)
/\S/ // Non-whitespace
/./ // Any char except newline
// Custom
/[abc]/ // Any of a, b, or c
/[a-z]/ // Range: a through z
/[^abc]/ // NOT a, b, or c (negation)
/[a-zA-Z]/ // Any letter
/[0-9]/ // Same as \dQuantifiers
/a*/ // 0 or more
/a+/ // 1 or more
/a?/ // 0 or 1
/a{3}/ // Exactly 3
/a{2,5}/ // 2 to 5
/a{2,}/ // 2 or more
// Greedy vs Lazy
/".+"/ // Greedy: matches "foo" and "bar" as one match in: "foo" and "bar"
/".+?"/ // Lazy: matches "foo" then "bar" separatelyAnchors and Boundaries
/^hello/ // Starts with "hello"
/world$/ // Ends with "world"
/\bhello\b/ // Whole word "hello" (word boundary)
/\Bhello/ // NOT at a word boundaryGroups and Alternation
// Capture group
/(foo|bar)/ // Matches "foo" or "bar", captures it
/(\d{3})-(\d{4})/ // Capture area code and number separately
// Non-capturing group
/(?:foo|bar)/ // Groups without capturing
// Named capture group
/(?<area>\d{3})-(?<number>\d{4})/
// Backreference
/(\w+)\s+\1/ // Matches repeated words: "the the"Lookahead and Lookbehind
// Positive lookahead: match "foo" followed by "bar"
/foo(?=bar)/ // "foobar" ✓ "foobaz" ✗
// Negative lookahead: match "foo" NOT followed by "bar"
/foo(?!bar)/ // "foobaz" ✓ "foobar" ✗
// Positive lookbehind: match "bar" preceded by "foo"
/(?<=foo)bar/ // "foobar" ✓ "bazbar" ✗
// Negative lookbehind: match "bar" NOT preceded by "foo"
/(?<!foo)bar/ // "bazbar" ✓ "foobar" ✗Flags
/pattern/g // Global — find all matches, not just the first
/pattern/i // Case-insensitive
/pattern/m // Multiline — ^ and $ match line starts/ends
/pattern/s // Dotall — . matches newlines too
/pattern/u // Unicode — proper Unicode support
/pattern/d // Indices — include start/end indices in results
/pattern/v // Unicode sets (ES2024) — set operations in character classes
// Combine flags
/pattern/gi // Global + case-insensitiveJavaScript Methods In Detail
test() — Boolean Check
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
emailRegex.test("user@site.com"); // true
emailRegex.test("not-an-email"); // false
// WARNING: test() with /g flag is stateful
const re = /a/g;
re.test("abc"); // true (lastIndex = 1)
re.test("abc"); // false (lastIndex = 0, reset)
re.test("abc"); // true (cycle repeats)exec() — Detailed Match Info
const dateRegex = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const result = dateRegex.exec("Date: 2024-03-15");
if (result) {
result[0]; // "2024-03-15" (full match)
result[1]; // "2024" (group 1)
result.index; // 6 (position in string)
result.groups?.year; // "2024"
result.groups?.month; // "03"
result.groups?.day; // "15"
}match() — String Method
// Without /g: same as exec()
"Price: $42.50".match(/\$(\d+\.\d{2})/);
// ["$42.50", "42.50", index: 7, groups: undefined]
// With /g: returns array of all matches (no groups)
"cat bat hat".match(/[a-z]at/g);
// ["cat", "bat", "hat"]matchAll() — Iterate All Matches with Groups
const text = "Jan 15, Feb 20, Mar 5";
const regex = /(?<month>[A-Z][a-z]+)\s+(?<day>\d+)/g;
for (const match of text.matchAll(regex)) {
console.log(`${match.groups?.month} ${match.groups?.day}`);
}
// "Jan 15"
// "Feb 20"
// "Mar 5"
// Or convert to array
const allMatches = [...text.matchAll(regex)];replace() and replaceAll()
// Simple replacement
"hello world".replace(/world/, "TypeScript"); // "hello TypeScript"
// Global replacement
"aabbcc".replace(/b/g, "X"); // "aaXXcc"
// With capture groups ($1, $2, etc.)
"John Smith".replace(/(\w+)\s(\w+)/, "$2, $1"); // "Smith, John"
// With named groups
"2024-01-15".replace(
/(?<y>\d{4})-(?<m>\d{2})-(?<d>\d{2})/,
"$<m>/$<d>/$<y>"
); // "01/15/2024"
// With a function
"hello world".replace(/\b\w/g, (char) => char.toUpperCase());
// "Hello World"
// Complex function replacement
"img_001.png, img_002.jpg".replace(
/img_(\d+)\.(png|jpg)/g,
(_match, num, ext) => `photo-${parseInt(num)}.${ext}`
);
// "photo-1.png, photo-2.jpg"split() — Split by Pattern
// Split by multiple delimiters
"one, two; three four".split(/[,;\s]+/);
// ["one", "two", "three", "four"]
// Split keeping the delimiter (capture group)
"one+two-three".split(/([+-])/);
// ["one", "+", "two", "-", "three"]
// Limit results
"a-b-c-d-e".split(/-/, 3);
// ["a", "b", "c"]Variations
Variation 1: Email Validation
// Basic email validation
const basicEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
// Stricter email (common real-world pattern)
const stricterEmail = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
basicEmail.test("user@example.com"); // true
basicEmail.test("user@sub.domain.co.uk"); // true
basicEmail.test("user@.com"); // falseVariation 2: URL Parsing
const urlRegex = /^(?<protocol>https?):\/\/(?<host>[^/:]+)(?::(?<port>\d+))?(?<path>\/[^?#]*)?(?:\?(?<query>[^#]*))?(?:#(?<fragment>.*))?$/;
const parsed = urlRegex.exec("https://example.com:8080/api/users?page=2#top");
if (parsed?.groups) {
parsed.groups.protocol; // "https"
parsed.groups.host; // "example.com"
parsed.groups.port; // "8080"
parsed.groups.path; // "/api/users"
parsed.groups.query; // "page=2"
parsed.groups.fragment; // "top"
}Variation 3: Password Strength Checker
function checkPasswordStrength(password: string): string[] {
const checks = [
{ regex: /.{8,}/, label: "At least 8 characters" },
{ regex: /[a-z]/, label: "Lowercase letter" },
{ regex: /[A-Z]/, label: "Uppercase letter" },
{ regex: /\d/, label: "A digit" },
{ regex: /[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/, label: "Special character" },
{ regex: /^(?!.*(.)\1{2})/, label: "No 3+ repeated characters" },
];
return checks.filter((c) => !c.regex.test(password)).map((c) => c.label);
}
checkPasswordStrength("weak"); // ["At least 8 characters", "Uppercase letter", "A digit", "Special character"]
checkPasswordStrength("Str0ng!Pass"); // []Variation 4: Slug Generator
function toSlug(text: string): string {
return text
.toLowerCase()
.trim()
.replace(/[^\w\s-]/g, "") // Remove non-word chars (except spaces and hyphens)
.replace(/[\s_]+/g, "-") // Replace spaces/underscores with hyphens
.replace(/-+/g, "-") // Collapse multiple hyphens
.replace(/^-|-$/g, ""); // Trim leading/trailing hyphens
}
toSlug("Hello, World! This is a Test"); // "hello-world-this-is-a-test"
toSlug(" --Foo & Bar-- "); // "foo--bar"Variation 5: Extract Numbers from Text
function extractNumbers(text: string): number[] {
return [...text.matchAll(/-?\d+\.?\d*/g)].map((m) => parseFloat(m[0]));
}
extractNumbers("Price: $42.50, Qty: 3, Discount: -5.25");
// [42.5, 3, -5.25]Variation 6: Template String Interpolation
function interpolate(template: string, vars: Record<string, string>): string {
return template.replace(/\{\{(\w+)\}\}/g, (_match, key: string) => vars[key] ?? `{{${key}}}`);
}
interpolate("Hello {{name}}, welcome to {{place}}!", {
name: "Alice",
place: "Wonderland",
});
// "Hello Alice, welcome to Wonderland!"Variation 7: Highlight Search Matches (React)
function highlightMatches(text: string, query: string): (string | JSX.Element)[] {
if (!query.trim()) return [text];
const escaped = query.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
const regex = new RegExp(`(${escaped})`, "gi");
const parts = text.split(regex);
return parts.map((part, i) =>
regex.test(part) ? <mark key={i} className="bg-yellow-200">{part}</mark> : part
);
}
// Usage: <p>{highlightMatches("Hello World", "world")}</p>
// Renders: Hello <mark>World</mark>Variation 8: Sanitize HTML Entities
function stripHtmlTags(html: string): string {
return html.replace(/<[^>]*>/g, "");
}
stripHtmlTags("<p>Hello <strong>world</strong></p>"); // "Hello world"
function escapeRegex(str: string): string {
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
escapeRegex("Price: $10.00 (USD)"); // "Price: \\$10\\.00 \\(USD\\)"Variation 9: Parse CSV Line
function parseCSVLine(line: string): string[] {
const result: string[] = [];
const regex = /(?:^|,)("(?:[^"]|"")*"|[^,]*)/g;
let match: RegExpExecArray | null;
while ((match = regex.exec(line)) !== null) {
let value = match[1];
if (value.startsWith('"') && value.endsWith('"')) {
value = value.slice(1, -1).replace(/""/g, '"');
}
result.push(value);
}
return result;
}
parseCSVLine('Alice,30,"New York, NY","She said ""hi"""');
// ["Alice", "30", "New York, NY", 'She said "hi"']Variation 10: Phone Number Formatter
function formatPhone(raw: string): string {
const digits = raw.replace(/\D/g, "");
const match = digits.match(/^(\d{1,3})?(\d{3})(\d{3})(\d{4})$/);
if (!match) return raw;
const [, country, area, prefix, line] = match;
return country ? `+${country} (${area}) ${prefix}-${line}` : `(${area}) ${prefix}-${line}`;
}
formatPhone("12125551234"); // "+1 (212) 555-1234"
formatPhone("2125551234"); // "(212) 555-1234"Variation 11: Credit Card Detection
const CARD_PATTERNS: Record<string, RegExp> = {
visa: /^4\d{12}(?:\d{3})?$/,
mastercard: /^5[1-5]\d{14}$/,
amex: /^3[47]\d{13}$/,
discover: /^6(?:011|5\d{2})\d{12}$/,
};
function detectCardType(number: string): string | null {
const cleaned = number.replace(/\D/g, "");
for (const [type, pattern] of Object.entries(CARD_PATTERNS)) {
if (pattern.test(cleaned)) return type;
}
return null;
}
detectCardType("4111 1111 1111 1111"); // "visa"
detectCardType("5500 0000 0000 0004"); // "mastercard"Variation 12: Extract Hashtags and Mentions
function extractHashtags(text: string): string[] {
return [...text.matchAll(/#(\w+)/g)].map((m) => m[1]);
}
function extractMentions(text: string): string[] {
return [...text.matchAll(/@(\w+)/g)].map((m) => m[1]);
}
const tweet = "Hey @alice and @bob, check out #TypeScript #React!";
extractHashtags(tweet); // ["TypeScript", "React"]
extractMentions(tweet); // ["alice", "bob"]Variation 13: IP Address Validation
const ipv4Regex = /^(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$/;
ipv4Regex.test("192.168.1.1"); // true
ipv4Regex.test("256.1.1.1"); // false
ipv4Regex.test("10.0.0.255"); // trueVariation 14: Markdown Link Extractor
function extractMarkdownLinks(md: string): Array<{ text: string; url: string }> {
return [...md.matchAll(/\[([^\]]+)\]\(([^)]+)\)/g)].map((m) => ({
text: m[1],
url: m[2],
}));
}
extractMarkdownLinks("Visit [Google](https://google.com) or [GitHub](https://github.com)");
// [{ text: "Google", url: "https://google.com" }, { text: "GitHub", url: "https://github.com" }]Variation 15: Camel Case / Snake Case Conversion
function camelToSnake(str: string): string {
return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
}
function snakeToCamel(str: string): string {
return str.replace(/_([a-z])/g, (_match, letter: string) => letter.toUpperCase());
}
camelToSnake("backgroundColor"); // "background_color"
snakeToCamel("background_color"); // "backgroundColor"
function toKebabCase(str: string): string {
return str
.replace(/([a-z])([A-Z])/g, "$1-$2")
.replace(/[\s_]+/g, "-")
.toLowerCase();
}
toKebabCase("backgroundColor"); // "background-color"
toKebabCase("Hello World"); // "hello-world"TypeScript Notes
// RegExp type
const pattern: RegExp = /\d+/g;
// RegExpMatchArray — returned by String.match() / RegExp.exec()
const result: RegExpMatchArray | null = "abc123".match(/(\d+)/);
if (result) {
const full: string = result[0];
const group: string = result[1];
const idx: number = result.index ?? 0;
}
// RegExpExecArray with named groups
const dateMatch = /(?<year>\d{4})-(?<month>\d{2})/.exec("2024-03");
if (dateMatch?.groups) {
// groups is Record<string, string> — requires optional chaining
const year: string | undefined = dateMatch.groups.year;
}
// Type-safe validator map
interface Validator {
pattern: RegExp;
message: string;
}
const validators: Record<string, Validator> = {
email: { pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/, message: "Invalid email" },
};
// Template literal type with regex validation (compile-time only)
type HexColor = `#${string}`;
function setColor(color: HexColor) { /* ... */ }
setColor("#ff0000"); // OK
// setColor("red"); // Type errorGotchas
-
test()with/gflag is stateful — The regex object trackslastIndex. Callingtest()repeatedly on different strings gives unexpected results. Fix: Omit thegflag when usingtest(), or create a new regex each time. -
Forgetting to escape special characters — Characters like
.,*,+,?,(,),[,{,$,^,|,\have special meaning. Fix: Use a helper:str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")to escape user input before building a regex. -
Greedy matching captures too much —
/".+"/.exec('"foo" and "bar"')matches"foo" and "bar"as one match. Fix: Use lazy quantifier".+?"to match the shortest possible string. -
match()with/gdrops capture groups — With the global flag,match()returns only full matches, not groups. Fix: UsematchAll()instead when you need group information with global matching. -
Catastrophic backtracking — Patterns like
/(a+)+$/on long non-matching strings can freeze the browser. Fix: Avoid nested quantifiers on the same characters. Use atomic patterns or test with ReDoS checkers. -
\bdoesn't work with Unicode — Word boundaries use ASCII definition of "word character" ([a-zA-Z0-9_]). Accented characters likeéare treated as non-word. Fix: Use the/uflag and explicit boundaries when working with international text. -
Newlines don't match
.— By default,.matches any character except\n. Fix: Use the/s(dotall) flag to make.match newlines, or use[\s\S]as a universal alternative. -
Forgetting
^and$anchors in validation —/\d+/.test("abc123xyz")returnstruebecause it finds digits anywhere. Fix: Use^and$to enforce full-string matching:/^\d+$/. -
replace()only replaces the first match — Without thegflag, only the first occurrence is replaced. Fix: Always use/gflag orreplaceAll()when you want to replace all occurrences. -
Building regex from user input without escaping — If a user types
(hello)into a search box and you usenew RegExp(input), it creates a capture group instead of matching literal parentheses. Fix: Always escape user input before passing tonew RegExp().
Alternatives
| Alternative | Use When | Don't Use When |
|---|---|---|
String.includes() | Simple substring check without pattern matching | You need wildcards or pattern logic |
String.startsWith() / endsWith() | Checking prefix or suffix | The prefix/suffix varies by pattern |
Zod .regex() | Schema validation in forms with zod | You need to extract or transform matched content |
| URL / URLSearchParams API | Parsing URLs | Matching arbitrary URL-like patterns in text |
Intl.NumberFormat | Formatting numbers for display | Extracting numbers from mixed text |
Parser libraries (e.g., date-fns) | Complex date/time parsing | Simple date format matching |
FAQs
What is the difference between test() and match()?
test()is a RegExp method that returns a boolean — use it when you only need to know if a pattern matchesmatch()is a String method that returns the match details (full match, groups, index) or nulltest()is faster when you don't need match details- Both are stateful with the
/gflag —test()updateslastIndexon the regex object
When should I use exec() vs matchAll()?
exec()returns one match at a time — call it in a loop with a/gregex to iteratematchAll()returns an iterator of all matches at once — cleaner and less error-pronematchAll()requires the/gflag;exec()works with or without it- Prefer
matchAll()in modern code — it avoids the statefullastIndexpitfall ofexec()loops
How do I safely use user input in a regex?
- Always escape special regex characters before using
new RegExp(userInput) - Use this escape function:
input.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") - Never pass raw user input to
new RegExp()— it can cause syntax errors or ReDoS attacks - Consider using
String.includes()for simple substring matching instead
What are named capture groups and why use them?
- Syntax:
(?<name>pattern)— assigns a name to a capture group - Access via
match.groups.nameinstead of positionalmatch[1] - Makes code more readable and less brittle when the regex changes
- Available in ES2018+ — supported in all modern browsers and Node.js 10+
What is catastrophic backtracking and how do I avoid it?
- Occurs when a regex has nested quantifiers like
(a+)+that create exponential matching paths - On non-matching input, the engine tries every combination before failing — can freeze the browser
- Avoid patterns like
(x+)+,(x+)*,(x*)*on the same character set - Test patterns with a ReDoS checker tool before using in production
- Use atomic groups or possessive quantifiers where available
How do lookaheads and lookbehinds differ from regular groups?
- Lookaheads
(?=...)and lookbehinds(?<=...)are zero-width — they assert a condition without consuming characters - Regular groups
(...)consume the matched text and include it in the result - Use positive lookahead
(?=...)to match "followed by" without including the following text - Use negative lookahead
(?!...)to match "NOT followed by" - Lookbehinds have the same logic but check what comes before the current position
Why does my regex work in a tester but not in TypeScript?
- Online testers may use different regex flavors (PCRE, Python, etc.) with features JavaScript lacks
- JavaScript doesn't support possessive quantifiers (
a++), atomic groups ((?>...)), or some PCRE syntax - The
/s(dotall) and/d(indices) flags were added in ES2018/ES2022 — older environments may not support them - Check that you're using the correct escape sequences — in
new RegExp("\\d")you need double backslashes
How should I type regex results in TypeScript?
RegExp.exec()andString.match()returnRegExpMatchArray | null— always null-check- Named groups are typed as
Record<string, string>on thegroupsproperty — use optional chaining - There's no built-in way to type specific group names — use a wrapper or assertion if needed
- For
matchAll(), the return type isIterableIterator<RegExpMatchArray>
What is the /u flag and when do I need it?
- The
/uflag enables full Unicode matching — without it, regex treats surrogate pairs as two characters - Needed when matching emoji, CJK characters, or any text outside the Basic Multilingual Plane
- Enables
\p{...}Unicode property escapes like\p{Letter}or\p{Emoji} - Always use
/uwhen working with international text to avoid subtle character-matching bugs
Should I use regex for email validation?
- A basic regex like
/^[^\s@]+@[^\s@]+\.[^\s@]+$/catches most typos and is fine for UX - No regex can fully validate an email per RFC 5322 — the spec is extremely complex
- For production, combine a simple regex check with a confirmation email or server-side validation
- Libraries like Zod provide
.email()validators that handle common edge cases
How do I match across multiple lines?
- By default,
^and$match start/end of the entire string - Use the
/m(multiline) flag to make^and$match start/end of each line - Use the
/s(dotall) flag to make.match newline characters - Alternatively, use
[\s\S]instead of.to match any character including newlines without the/sflag
What is the difference between replace() and replaceAll()?
replace()without/greplaces only the first matchreplace()with/greplaces all matchesreplaceAll()always replaces all matches — requires/gflag if passed a regexreplaceAll()with a string argument replaces all occurrences without needing regexreplaceAll()was added in ES2021 — usereplace(/pattern/g, ...)for older environments
Related
- TypeScript Basics — Core TypeScript concepts used in regex typing
- Utility Types for React — Record and other types used in validator patterns
- Type Narrowing — Null checks after regex match operations