Referencia de expresiones regulares
Una referencia completa para expresiones regulares de JavaScript/TypeScript - sintaxis, banderas, métodos y patrones del mundo real comúnmente usados en aplicaciones React.
Busca en todas las páginas de la documentación
Una referencia completa para expresiones regulares de JavaScript/TypeScript - sintaxis, banderas, métodos y patrones del mundo real comúnmente usados en aplicaciones React.
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥
| Método | Devuelve | Descripción |
|---|---|---|
regex.test(str) | boolean | Devuelve true si el patrón coincide en cualquier lugar de la cadena |
regex.exec(str) | RegExpExecArray | null | Devuelve detalles de coincidencia (grupos, índice) o null |
str.match(regex) | RegExpMatchArray | null | Devuelve coincidencias - el comportamiento cambia con la bandera g |
str.matchAll(regex) | IterableIterator<RegExpMatchArray> | Devuelve iterador de todas las coincidencias (requiere bandera g) |
str.search(regex) | number | Devuelve el índice de la primera coincidencia, o -1 |
str.replace(regex, replacement) | string | Reemplaza la primera coincidencia (o todas con bandera g) |
str.replaceAll(regex, replacement) | string | Reemplaza todas las coincidencias (requiere bandera g) |
str.split(regex) | string[] | Divide la cadena por coincidencias de expresión regular |
Referencia rápida - operaciones de expresión regular más comunes en TypeScript.
// Comprueba si una cadena coincide
const isEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test("user@example.com"); // true
// Extrae coincidencias
const matches = "2024-01-15".match(/(\d{4})-(\d{2})-(\d{2})/);
// matches[1] = "2024", matches[2] = "01", matches[3] = "15"
// Grupos de captura nombrados
const result = "2024-01-15".match(/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/);
// result?.groups?.year = "2024"
// Reemplaza con patrón
const slug = "Hello World! Foo".replace(/[^a-zA-Z0-9]+/g, "-").toLowerCase();
// "hello-world-foo"
// Divide por patrón
const words = "one, two; three".split(/[,;]\s*/);
// ["one", "two", "three"]Cuándo usar esto: Validación de entrada, análisis de texto, enrutamiento de URL, lógica de búsqueda/filtrado y transformación de datos en formularios y utilidades.
"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: "Debe ser una dirección de correo electrónico válida",
},
phone: {
pattern: /^\+?[\d\s\-()]{7,15}$/,
message: "Debe ser un número de teléfono válido (7-15 dígitos)",
},
url: {
pattern: /^https?:\/\/[^\s/$.?#].[^\s]*$/i,
message: "Debe ser una URL válida comenzando con http(s)://",
},
zipCode: {
pattern: /^\d{5}(-\d{4})?$/,
message: "Debe ser un código postal estadounidense válido (12345 o 12345-6789)",
},
password: {
pattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*]).{8,}$/,
message: "Mín 8 caracteres, 1 mayúscula, 1 minúscula, 1 dígito, 1 carácter especial",
},
};
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 ? "Válido" : 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={`Ingresa ${selected}...`}
className="border rounded px-2 py-1 w-full"
/>
<button onClick={validate} className="bg-blue-600 text-white px-4 py-1 rounded">
Validar
</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>
);
}Lo que esto demuestra:
RegExp.test() para validación booleana// Predefinidos
/\d/ // Dígito [0-9]
/\D/ // No dígito [^0-9]
/\w/ // Carácter de palabra [a-zA-Z0-9_]
/\W/ // Carácter que no es de palabra
/\s/ // Espacio en blanco (espacio, tabulación, salto de línea)
/\S/ // No espacio en blanco
/./ // Cualquier carácter excepto salto de línea
// Personalizados
/[abc]/ // Cualquiera de a, b o c
/[a-z]/ // Rango: a a z
/[^abc]/ // NO a, b o c (negación)
/[a-zA-Z]/ // Cualquier letra
/[0-9]/ // Igual que \d/a*/ // 0 o más
/a+/ // 1 o más
/a?/ // 0 o 1
/a{3}/ // Exactamente 3
/a{2,5}/ // 2 a 5
/a{2,}/ // 2 o más
// Codicioso vs perezoso
/".+"/ // Codicioso: coincide "foo" y "bar" como una coincidencia en: "foo" y "bar"
/".+?"/ // Perezoso: coincide "foo" luego "bar" por separado/^hello/ // Comienza con "hello"
/world$/ // Termina con "world"
/\bhello\b/ // Palabra completa "hello" (límite de palabra)
/\Bhello/ // NO en un límite de palabra// Grupo de captura
/(foo|bar)/ // Coincide "foo" o "bar", lo captura
/(\d{3})-(\d{4})/ // Captura código de área y número por separado
// Grupo sin captura
/(?:foo|bar)/ // Agrupa sin capturar
// Grupo de captura nombrado
/(?<area>\d{3})-(?<number>\d{4})/
// Referencia hacia atrás
/(\w+)\s+\1/ // Coincide palabras repetidas: "the the"// Anticipación positiva: coincide "foo" seguido de "bar"
/foo(?=bar)/ // "foobar" ✓ "foobaz" ✗
// Anticipación negativa: coincide "foo" NO seguido de "bar"
/foo(?!bar)/ // "foobaz" ✓ "foobar" ✗
// Retrospectiva positiva: coincide "bar" precedido de "foo"
/(?<=foo)bar/ // "foobar" ✓ "bazbar" ✗
// Retrospectiva negativa: coincide "bar" NO precedido de "foo"
/(?<!foo)bar/ // "bazbar" ✓ "foobar" ✗/pattern/g // Global - encuentra todas las coincidencias, no solo la primera
/pattern/i // Insensible a mayúsculas y minúsculas
/pattern/m // Multilínea - ^ y $ coinciden con inicios/finales de línea
/pattern/s // Dotall - . coincide también con saltos de línea
/pattern/u // Unicode - soporte Unicode adecuado
/pattern/d // Índices - incluye índices de inicio/fin en resultados
/pattern/v // Conjuntos Unicode (ES2024) - operaciones de conjunto en clases de caracteres
// Combina banderas
/pattern/gi // Global + insensible a mayúsculastest() - Comprobación booleanaconst emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
emailRegex.test("user@site.com"); // true
emailRegex.test("not-an-email"); // false
// ADVERTENCIA: test() con bandera /g tiene estado
const re = /a/g;
re.test("abc"); // true (lastIndex = 1)
re.test("abc"); // false (lastIndex = 0, reinicia)
re.test("abc"); // true (el ciclo se repite)exec() - Información detallada de coincidenciaconst 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" (coincidencia completa)
result[1]; // "2024" (grupo 1)
result.index; // 6 (posición en cadena)
result.groups?.year; // "2024"
result.groups?.month; // "03"
result.groups?.day; // "15"
}match() - Método de cadena// Sin /g: igual que exec()
"Price: $42.50".match(/\$(\d+\.\d{2})/);
// ["$42.50", "42.50", index: 7, groups: undefined]
// Con /g: devuelve array de todas las coincidencias (sin grupos)
"cat bat hat".match(/[a-z]at/g);
// ["cat", "bat", "hat"]matchAll() - Itera todas las coincidencias con gruposconst 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"
// O convierte a array
const allMatches = [...text.matchAll(regex)];replace() y replaceAll()// Reemplazo simple
"hello world".replace(/world/, "TypeScript"); // "hello TypeScript"
// Reemplazo global
"aabbcc".replace(/b/g, "X"); // "aaXXcc"
// Con grupos de captura ($1, $2, etc.)
"John Smith".replace(/(\w+)\s(\w+)/, "$2, $1"); // "Smith, John"
// Con grupos nombrados
"2024-01-15".replace(
/(?<y>\d{4})-(?<m>\d{2})-(?<d>\d{2})/,
"$<m>/$<d>/$<y>"
); // "01/15/2024"
// Con una función
"hello world".replace(/\b\w/g, (char) => char.toUpperCase());
// "Hello World"
// Reemplazo de función compleja
"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() - Divide por patrón// Divide por múltiples delimitadores
"one, two; three four".split(/[,;\s]+/);
// ["one", "two", "three", "four"]
// Divide manteniendo el delimitador (grupo de captura)
"one+two-three".split(/([+-])/);
// ["one", "+", "two", "-", "three"]
// Limita resultados
"a-b-c-d-e".split(/-/, 3);
// ["a", "b", "c"]Variación 1: Validación de correo electrónico
// Validación básica de correo electrónico
const basicEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
// Correo electrónico más estricto (patrón común del mundo real)
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"); // falseVariación 2: Análisis de URL
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"
}Variación 3: Verificador de fortaleza de contraseña
function checkPasswordStrength(password: string): string[] {
const checks = [
{ regex: /.{8,}/, label: "Al menos 8 caracteres" },
{ regex: /[a-z]/, label: "Letra minúscula" },
{ regex: /[A-Z]/, label: "Letra mayúscula" },
{ regex: /\d/, label: "Un dígito" },
{ regex: /[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/, label: "Carácter especial" },
{ regex: /^(?!.*(.)\1{2})/, label: "Sin 3+ caracteres repetidos" },
];
return checks.filter((c) => !c.regex.test(password)).map((c) => c.label);
}
checkPasswordStrength("weak"); // ["Al menos 8 caracteres", "Letra mayúscula", "Un dígito", "Carácter especial"]
checkPasswordStrength("Str0ng!Pass"); // []Variación 4: Generador de slug
function toSlug(text: string): string {
return text
.toLowerCase()
.trim()
.replace(/[^\w\s-]/g, "") // Elimina caracteres que no sean palabra (excepto espacios e guiones)
.replace(/[\s_]+/g, "-") // Reemplaza espacios/guiones bajos con guiones
.replace(/-+/g, "-") // Colapsa múltiples guiones
.replace(/^-|-$/g, ""); // Recorta guiones iniciales/finales
}
toSlug("Hello, World! This is a Test"); // "hello-world-this-is-a-test"
toSlug(" --Foo & Bar-- "); // "foo--bar"Variación 5: Extrae números del texto
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]Variación 6: Interpolación de cadena de plantilla
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!"Variación 7: Resalta coincidencias de búsqueda (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
);
}
// Uso: <p>{highlightMatches("Hello World", "world")}</p>
// Renderiza: Hello <mark>World</mark>Variación 8: Sanitiza entidades HTML
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\\)"Variación 9: Analiza línea CSV
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"']Variación 10: Formateador de número de teléfono
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"Variación 11: Detección de tarjeta de crédito
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"Variación 12: Extrae hashtags y menciones
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"]Variación 13: Validación de dirección IP
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"); // trueVariación 14: Extractor de enlace Markdown
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" }]Variación 15: Conversión entre camelCase y snake_case
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"// Tipo RegExp
const pattern: RegExp = /\d+/g;
// RegExpMatchArray - devuelto por 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 con grupos nombrados
const dateMatch = /(?<year>\d{4})-(?<month>\d{2})/.exec("2024-03");
if (dateMatch?.groups) {
// groups es Record<string, string> - requiere encadenamiento opcional
const year: string | undefined = dateMatch.groups.year;
}
// Mapa de validador con seguridad de tipo
interface Validator {
pattern: RegExp;
message: string;
}
const validators: Record<string, Validator> = {
email: { pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/, message: "Correo electrónico inválido" },
};
// Tipo de literal de plantilla con validación de expresión regular (solo en tiempo de compilación)
type HexColor = `#${string}`;
function setColor(color: HexColor) { /* ... */ }
setColor("#ff0000"); // OK
// setColor("red"); // Error de tipotest() con bandera /g tiene estado - El objeto de expresión regular rastrea lastIndex. Llamar a test() repetidamente en diferentes cadenas da resultados inesperados. Solución: Omite la bandera g cuando uses test(), o crea una nueva expresión regular cada vez.
Olvidar escapar caracteres especiales - Caracteres como ., *, +, ?, (, ), [, {, $, ^, |, \ tienen significado especial. Solución: Usa un ayudante: str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") para escapar entrada del usuario antes de construir una expresión regular.
Coincidencia codiciosa captura demasiado - /".+"/.exec('"foo" and "bar"') coincide "foo" and "bar" como una coincidencia. Solución: Usa cuantificador perezoso ".+?" para coincidir la cadena más corta posible.
match() con /g elimina grupos de captura - Con la bandera global, match() devuelve solo coincidencias completas, no grupos. Solución: Usa matchAll() en su lugar cuando necesites información de grupo con coincidencia global.
Retroceso catastrófico - Patrones como /(a+)+$/ en cadenas largas que no coinciden pueden congelar el navegador. Solución: Evita cuantificadores anidados en los mismos caracteres. Usa patrones atómicos o prueba con verificadores de ReDoS.
\b no funciona con Unicode - Los límites de palabra usan la definición ASCII de "carácter de palabra" ([a-zA-Z0-9_]). Caracteres acentuados como é se tratan como no-palabra. Solución: Usa la bandera /u y límites explícitos cuando trabajes con texto internacional.
Los saltos de línea no coinciden con . - Por defecto, . coincide con cualquier carácter excepto \n. Solución: Usa la bandera /s (dotall) para hacer que . coincida con saltos de línea, o usa [\s\S] como alternativa universal.
Olvidar anclajes ^ y $ en validación - /\d+/.test("abc123xyz") devuelve true porque encuentra dígitos en cualquier lugar. Solución: Usa ^ y $ para reforzar coincidencia de cadena completa: /^\d+$/.
replace() solo reemplaza la primera coincidencia - Sin la bandera g, solo se reemplaza la primera ocurrencia. Solución: Siempre usa bandera /g o replaceAll() cuando quieras reemplazar todas las ocurrencias.
Construir expresión regular de entrada del usuario sin escapar - Si un usuario escribe (hello) en una caja de búsqueda y usas new RegExp(input), crea un grupo de captura en lugar de coincidir paréntesis literales. Solución: Siempre escapa entrada del usuario antes de pasar a new RegExp().
| Alternativa | Usa cuando | No uses cuando |
|---|---|---|
String.includes() | Comprobación de subcadena simple sin coincidencia de patrón | Necesitas comodines o lógica de patrón |
String.startsWith() / endsWith() | Comprobar prefijo o sufijo | El prefijo/sufijo varía por patrón |
Zod .regex() | Validación de esquema en formularios con zod | Necesitas extraer o transformar contenido coincidente |
| URL / URLSearchParams API | Analizar URLs | Coincidir patrones similares a URL arbitrarios en texto |
Intl.NumberFormat | Formatear números para visualización | Extraer números de texto mixto |
Librerías de analizador (p. ej., date-fns) | Análisis complejo de fecha/hora | Coincidencia de formato de fecha simple |
test() es un método de RegExp que devuelve un booleano - úsalo cuando solo necesites saber si un patrón coincidematch() es un método de String que devuelve los detalles de coincidencia (coincidencia completa, grupos, índice) o nulltest() es más rápido cuando no necesitas detalles de coincidencia/g - test() actualiza lastIndex en el objeto de expresión regularexec() devuelve una coincidencia a la vez - llámalo en un bucle con una expresión regular /g para iterarmatchAll() devuelve un iterador de todas las coincidencias a la vez - más limpio y menos propenso a erroresmatchAll() requiere la bandera /g; exec() funciona con o sin ellamatchAll() en código moderno - evita la trampa con estado lastIndex de bucles exec()new RegExp(userInput)input.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")new RegExp() - puede causar errores de sintaxis o ataques ReDoSString.includes() para coincidencia de subcadena simple en su lugar(?<name>pattern) - asigna un nombre a un grupo de capturamatch.groups.name en lugar de match[1] posicional(a+)+ que crean rutas de coincidencia exponenciales(x+)+, (x+)*, (x*)* en el mismo conjunto de caracteres(?=...) y retrospectiva (?<=...) son de ancho cero - afirman una condición sin consumir caracteres(...) consumen el texto coincidente e lo incluyen en el resultado(?=...) para coincidir "seguido de" sin incluir el texto siguiente(?!...) para coincidir "NO seguido de"a++), grupos atómicos ((?>...)), o alguna sintaxis PCRE/s (dotall) y /d (indices) fueron agregadas en ES2018/ES2022 - ambientes antiguos pueden no soportarlasnew RegExp("\\d") necesitas barras invertidas doblesRegExp.exec() y String.match() devuelven RegExpMatchArray | null - siempre null-verificaRecord<string, string> en la propiedad groups - usa encadenamiento opcionalmatchAll(), el tipo de devolución es IterableIterator<RegExpMatchArray>/u habilita coincidencia Unicode completa - sin ella, la expresión regular trata pares sustitutos como dos caracteres\p{...} como \p{Letter} o \p{Emoji}/u cuando trabajes con texto internacional para evitar errores sutiles de coincidencia de caracteres/^[^\s@]+@[^\s@]+\.[^\s@]+$/ atrapa la mayoría de errores tipográficos y está bien para UX.email() que manejan casos extremos comunes^ y $ coinciden con inicio/fin de toda la cadena/m (multilínea) para hacer que ^ y $ coincidan con inicio/fin de cada línea/s (dotall) para hacer que . coincida con caracteres de salto de línea[\s\S] en lugar de . para coincidir cualquier carácter incluyendo saltos de línea sin la bandera /sreplace() sin /g reemplaza solo la primera coincidenciareplace() con /g reemplaza todas las coincidenciasreplaceAll() siempre reemplaza todas las coincidencias - requiere bandera /g si se pasa una expresión regularreplaceAll() con un argumento de cadena reemplaza todas las ocurrencias sin necesidad de expresión regularreplaceAll() fue agregado en ES2021 - usa replace(/pattern/g, ...) para ambientes antiguosRevisado por Chris St. John·Última actualización: 10 jul 2026
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥