Patrones de regex que todo desarrollador debería conocer
Referencia práctica de las expresiones regulares que de verdad usarás a diario: validación, análisis y búsqueda y reemplazo.

Las expresiones regulares provocan una reacción visceral en los desarrolladores. La sintaxis es críptica, el comportamiento es sorprendente, y los memes sobre «ahora tienes dos problemas» están más que merecidos. Pero el regex no va a desaparecer. Aparece en la validación de formularios, el análisis de logs, la búsqueda y reemplazo, el enrutamiento, las reglas de linting y en muchos otros contextos.
El problema no es el regex en sí. Es que la mayoría de los desarrolladores aprenden regex a base de prueba y error en StackOverflow, en lugar de entender los bloques que lo componen. Una vez que conoces los elementos primitivos, componer patrones se vuelve predecible.
Los bloques fundamentales
Todo patrón de regex es una combinación de seis conceptos: literales, clases de caracteres, cuantificadores, anclas, grupos y alternancia. Esa es toda la base.
// Literals: match exact characters
/hello/ // matches "hello" in "say hello world"
// Character classes: match any character in a set
/[aeiou]/ // matches any vowel
/[^0-9]/ // matches any non-digit
/\d/ // shorthand for [0-9]
/\w/ // shorthand for [a-zA-Z0-9_]
/\s/ // shorthand for whitespace
// Quantifiers: how many times to match
/a*/ // 0 or more 'a'
/a+/ // 1 or more 'a'
/a?/ // 0 or 1 'a'
/a{3}/ // exactly 3 'a's
/a{2,5}/ // between 2 and 5 'a's
// Anchors: position in the string
/^start/ // starts with "start"
/end$/ // ends with "end"
/\bword\b/ // whole word "word"Eso es todo. Todo lo demás es una composición de estos seis conceptos. El patrón de aspecto críptico ^\w+@[\w.-]+\.\w{2,}$ es simplemente: inicio de cadena, uno o más caracteres de palabra, el carácter literal @, caracteres de palabra/puntos/guiones, un punto literal, 2 o más caracteres de palabra, fin de cadena.
Patrones de validación
La validación de formularios es el caso de uso más común de regex. Estos patrones cubren las entradas que verás con más frecuencia.
const patterns = {
// Email — simplified but practical
// (Full RFC 5322 compliance requires a parser, not regex)
email: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
// URL — http/https with optional path
url: /^https?:\/\/[\w.-]+(?:\.[\w.-]+)+[\w\-._~:/?#[\]@!$&'()*+,;=]*$/,
// Phone — flexible international format
phone: /^\+?[\d\s\-().]{7,20}$/,
// Slug — URL-safe identifier
slug: /^[a-z0-9]+(?:-[a-z0-9]+)*$/,
// Hex color — 3 or 6 digit
hexColor: /^#(?:[0-9a-fA-F]{3}){1,2}$/,
// ISO date — YYYY-MM-DD
isoDate: /^\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])$/,
};
function validate(value: string, pattern: RegExp): boolean {
return pattern.test(value);
}// ❌ Overly strict email regex — rejects valid addresses
const strictEmail = /^[a-z]+\.[a-z]+@[a-z]+\.com$/;
// Rejects: user+tag@domain.co.uk, UPPER@domain.com
// ✅ Practical email regex — catches obvious errors
const practicalEmail = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
// Validates structure without being overly restrictiveEl debate sobre el regex de email es eterno. La respuesta pragmática: usa una verificación estructural básica con regex y luego confirma la propiedad enviando un correo de confirmación.
Grupos de captura y extracción
Los grupos () capturan subcadenas coincidentes para su extracción. Los grupos con nombre (?<name>) hacen que los resultados se documenten por sí mismos.
// Parse a log line with named groups
const logPattern = /^(?<timestamp>\d{4}-\d{2}-\d{2}T[\d:.]+Z)\s+(?<level>INFO|WARN|ERROR)\s+(?<message>.+)$/;
const line = '2020-12-02T14:30:00.000Z ERROR Connection timeout to database';
const match = line.match(logPattern);
if (match?.groups) {
console.log(match.groups.timestamp); // 2020-12-02T14:30:00.000Z
console.log(match.groups.level); // ERROR
console.log(match.groups.message); // Connection timeout to database
}Los grupos que no capturan (?:) agrupan sin capturar — útiles cuando necesitas agrupar para los cuantificadores, pero no necesitas la coincidencia:
// Match file extensions — capture the name, not the dot group
const filePattern = /^(?<name>[\w.-]+)\.(?<ext>tsx?|jsx?|css|html)$/;
const match = 'component.tsx'.match(filePattern);
// match.groups.name = "component"
// match.groups.ext = "tsx"Patrones de búsqueda y reemplazo
El reemplazo con regex es donde viven las verdaderas ganancias de productividad. Un solo reemplazo con regex puede hacer el trabajo de 50 ediciones manuales.
// Convert camelCase to kebab-case
function toKebab(str: string): string {
return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
}
// "backgroundColor" → "background-color"
// Strip HTML tags
function stripTags(html: string): string {
return html.replace(/<[^>]*>/g, '');
}
// Mask sensitive data in logs
function maskEmail(text: string): string {
return text.replace(
/([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/g,
'***@$2'
);
}
// "Contact user@example.com" → "Contact ***@example.com"Las referencias inversas $1, $2 en las cadenas de reemplazo hacen referencia a los grupos capturados. Esto hace posibles las transformaciones estructurales sin necesidad de un parser.
// Reformat dates from MM/DD/YYYY to YYYY-MM-DD
function reformatDate(text: string): string {
return text.replace(
/(\d{2})\/(\d{2})\/(\d{4})/g,
'$3-$1-$2'
);
}
// "12/02/2020" → "2020-12-02"Lookahead y lookbehind
El lookahead (?=) y el lookbehind (?<=) coinciden con posiciones sin consumir caracteres. Son aserciones, no coincidencias.
// Password validation — all conditions must be true
// At least 8 chars, one uppercase, one lowercase, one digit
const strongPassword = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/;
// Match numbers NOT followed by a unit (find raw numbers)
const rawNumbers = /\d+(?!\s*(?:px|em|rem|%))/g;
'16px 24 32rem 48'.match(rawNumbers); // ["24", "48"]
// Match currency amounts (number preceded by $)
const amounts = /(?<=\$)\d+(?:\.\d{2})?/g;
'Price: $19.99 and $5'.match(amounts); // ["19.99", "5"]Los lookaheads son compatibles en todas partes. Los lookbehinds requieren ES2018+ (Chrome 62+, Node 8.10+, Firefox 78+). Para entornos más antiguos, usa grupos de captura en su lugar.
Rendimiento y seguridad
El regex puede ser peligroso. El backtracking catastrófico ocurre cuando un patrón con cuantificadores anidados se encuentra con una entrada que fuerza una exploración exponencial.
// ❌ Catastrophic backtracking — O(2^n) on bad input
const bad = /^(a+)+$/;
bad.test('aaaaaaaaaaaaaaaaaaaaaaab'); // Hangs for seconds
// ❌ Another common disaster — nested repetition
const evil = /^(\w+\s?)+$/;
evil.test('a b c d e f g h i j k !'); // Exponential backtracking
// ✅ Avoid nested quantifiers on overlapping patterns
const safe = /^[a\s]+$/;
const alsoSafe = /^\w+(?:\s\w+)*$/;Reglas para un regex seguro:
- Nunca anides cuantificadores en patrones que puedan coincidir con los mismos caracteres
- Usa grupos atómicos o cuantificadores posesivos cuando estén disponibles
- Establece un tiempo límite al ejecutar patrones de regex proporcionados por el usuario
- Prefiere los cuantificadores perezosos
*?y+?cuando necesites la coincidencia más corta
// When accepting regex from users, always set a timeout
function safeRegexTest(pattern: string, input: string, timeoutMs = 100): boolean {
const start = performance.now();
try {
const regex = new RegExp(pattern);
const result = regex.test(input);
if (performance.now() - start > timeoutMs) {
throw new Error('Regex execution exceeded timeout');
}
return result;
} catch {
return false;
}
}Puntos clave
- El regex tiene seis bloques fundamentales — literales, clases de caracteres, cuantificadores, anclas, grupos y alternancia lo cubren todo
- Los grupos con nombre hacen que los patrones sean legibles —
(?<name>...)se documenta a sí mismo, a diferencia de$1y$2 - El regex de validación debe ser práctico, no perfecto — una verificación básica de email más un correo de confirmación superan a un regex conforme al RFC
- La búsqueda y reemplazo es la habilidad de regex con mayor impacto — un solo patrón puede reemplazar 50 ediciones manuales
- Cuidado con el backtracking catastrófico — los cuantificadores anidados en patrones superpuestos crean un tiempo de ejecución exponencial


