Guía rápida de Regex gratuita
Guía de referencia interactiva para expresiones regulares.
Probar un patrón
Cómo usar
- Explora las categorías de patrones o usa la barra de búsqueda para encontrar un patrón preciso.
- Introduce una expresión regular en el campo «Probar un patrón» y un texto de ejemplo en «Texto de prueba».
- Activa/desactiva los flags (global, insensible a mayúsculas, multilínea) y ve las coincidencias resaltadas al instante.
Preguntas frecuentes
¿Qué es una expresión regular?
Una expresión regular (regex o regexp) es un patrón que sirve para buscar, encontrar y reemplazar texto. Usa caracteres y una sintaxis especiales para definir las cadenas que se buscan.
¿Para qué sirven los flags?
Global (g) busca todas las coincidencias. Insensible a mayúsculas (i) ignora la caja de las letras. Multilínea (m) hace que ^ y $ coincidan con los límites de línea en lugar de los límites de cadena.
¿Puedo usar esta chuleta en mi código?
¡Sí! Cuando hayas probado un patrón y verificado que funciona, copia el patrón regex directamente en tu código JavaScript, Python o cualquier otro lenguaje.
Una breve historia del lenguaje de patrones
Las expresiones regulares empezaron como un trozo de informática teórica. Stephen Kleene definió los «conjuntos regulares» en un artículo de 1956 sobre redes neuronales; Ken Thompson las metió en Unix en 1968 con grep. La biblioteca regex open-source de Henry Spencer (mediados de los 80) fue la base de muchas implementaciones posteriores. Larry Wall extendió la sintaxis dramáticamente en Perl, y sus «expresiones regulares compatibles con Perl» (PCRE) se convirtieron en el estándar de facto que la mayoría de los lenguajes modernos siguieron. Hoy hay varios sabores de regex estrechamente relacionados pero sutilmente distintos, y un patrón que funciona en un motor no siempre funciona idénticamente en otro.
El motor en el que vive tu patrón
La misma sintaxis puede significar cosas distintas en motores distintos. Las grandes familias:
- POSIX BRE (Basic Regular Expressions), usada por el modo por defecto de
grep,sed. Muchos metacaracteres requieren escapado con barra invertida:(,),{,},+,?,|son literales si no se escapan. - POSIX ERE (Extended Regular Expressions), usada por
egrep,awk. Los metacaracteres anteriores funcionan sin escapar. - PCRE (Perl-Compatible Regular Expressions), extiende ERE con lookarounds, atomic groups, capturas con nombre y backreferences. Usada por PHP y la mayoría de los lenguajes modernos. Las clases abreviadas derivadas de Perl
\d/\w/\sson comunes a PCRE, JavaScript, .NET, Java y Python. - JavaScript RegExp, cercana a PCRE pero con diferencias notables. ES2018 añadió lookbehinds, grupos de captura con nombre, el flag dotall
sy los Unicode property escapes vía el flagu. El flagvpara notación de conjuntos llegó en ES2024. rede Python yregexde Python,reestá en la biblioteca estándar; el módulo de tercerosregexañade funcionalidades Unicode-aware, lookbehinds de ancho variable y otras mejoras tipo PCRE.- RE2 (la biblioteca de Google, usada en Go), garantiza tiempo lineal pero no soporta backreferences ni lookarounds. El compromiso: rendimiento predecible, menos funcionalidades.
El probador interactivo de esta chuleta corre en JavaScript, así que el patrón lo evalúa el motor JS del navegador. Los patrones que funcionan aquí pueden comportarse de forma distinta en Python o PHP. La mayoría de las diferencias están en funcionalidades avanzadas (lookbehinds, Unicode property escapes, backreferences) más que en la sintaxis básica.
Los bloques de construcción centrales
Casi todo patrón regex se construye a partir de estos elementos:
- Literales, se corresponden a sí mismos.
catcoincide con la subcadena «cat». - Anclas,
^(inicio de cadena / línea),$(final),\b(frontera de palabra),\B(no-frontera de palabra). - Clases de carácter,
[abc]coincide con a, b o c.[^abc]niega.[a-z]es un rango. Abreviaturas:\d(dígito),\w(carácter de palabra: letra, dígito, guion bajo),\s(espacio en blanco) y versiones en mayúscula para negación (\D,\W,\S). - Cuantificadores,
?(0 o 1),*(0 o más),+(1 o más),{n},{n,},{n,m}. Codiciosos por defecto (coinciden con tanto como sea posible); añade?para perezoso:*?,+?,??. - Grupos,
(...)capturador,(?:...)no capturador,(?<name>...)con nombre (PCRE / JS / Python). - Alternancia,
cat|dogcoincide con cualquiera de los dos. - Lookarounds,
(?=...)lookahead positivo,(?!...)lookahead negativo,(?<=...)lookbehind positivo,(?<!...)lookbehind negativo. Coinciden sin consumir. - Backreferences,
\1,\2(numeradas),\k<name>(con nombre). Coinciden con el mismo texto que coincidió en la captura correspondiente. - Flags,
g(global),i(insensible a mayúsculas),m(multilínea:^y$coinciden con fronteras de línea),s(dotall:.coincide con saltos de línea),u(Unicode),y(sticky en JS).
Patrones que merece la pena memorizar
Un puñado de patrones aparecen tan a menudo que merece la pena tenerlos en la cabeza:
| Uso | Patrón |
|---|---|
| Email (básico) | ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ |
| URL | https?://[^\s]+ |
| Número de teléfono de EE.UU. | \(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4} |
| Fecha ISO (YYYY-MM-DD) | \d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]) |
| Dirección IPv4 (sin validación de octeto) | \b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b |
| Color hex | ^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$ |
| Espacio en blanco al inicio/final de línea | ^\s+|\s+$ |
| Múltiples espacios consecutivos | \s{2,} |
Una nota sobre regex de email: la validación completa RFC 5322 necesita una regex monstruo de 6.000 caracteres. La forma simple anterior acepta el 99% de las direcciones de email reales y no rechaza ninguna legítima; en producción, envía un email de confirmación en lugar de intentar validar perfectamente la sintaxis.
Codicioso vs perezoso: una sorpresa común
Por defecto, los cuantificadores son codiciosos: coinciden con tanto como sea posible mientras el patrón global siga pudiendo coincidir. Así que <.+> contra <a>text</a> coincide con todo, no sólo con <a>, porque .+ agarra todo lo que puede. Para coincidir con la cadena más pequeña posible, añade ? al cuantificador: <.+?> coincide con <a> y luego con </a> por separado. La elección codicioso/perezoso es una de las fuentes más comunes de bugs «¿por qué mi regex no coincide con lo que esperaba?».
Backtracking catastrófico y ReDoS
Algunos patrones regex pueden tardar tiempo exponencial en fallar sobre ciertos inputs, una clase de vulnerabilidad de denegación de servicio llamada ReDoS (Regular Expression Denial of Service). Los culpables clásicos son los cuantificadores anidados como (a+)+ o (a|aa)+ aplicados a una cadena larga de as seguida de un carácter que no encaja. El motor prueba cada forma posible de partir la cadena antes de rendirse, y el número de formas es exponencial.
Incidentes del mundo real: la caída de Cloudflare en 2019 la disparó una regex desplegada en una regla WAF que backtrackeó catastróficamente sobre ciertos inputs. Stack Overflow tuvo un incidente similar en julio de 2016: una regex de post-trim (^[\s]+|[\s]+$) chocó con un backtracking exponencial en un único comentario que contenía aproximadamente 20.000 caracteres de espacio en blanco consecutivos y tumbó el sitio durante 34 minutos. Hábitos defensivos: evita cuantificadores anidados, prefiere atomic groups ((?>...)) donde estén soportados, y considera usar RE2 / motores de tiempo lineal para input no confiable.
Peculiaridades por lenguaje que conviene conocer
- JavaScript: las barras invertidas necesitan doble escapado en literales de cadena (
"\\d") pero no en literales regex (/\d/). Usa la forma literal regex cuando puedas. - Python: usa cadenas crudas (
r"\d+") para evitar problemas de barra invertida. El móduloreestá en la biblioteca estándar;regexen PyPI añade funcionalidades extra. - Java: las barras invertidas necesitan cuádruple escapado (
"\\\\d"para\d) porque los literales de cadena de Java usan\como escape y el compilador regex luego ve\\d. - Bash: el matching regex en
[[ string =~ pattern ]]usa POSIX ERE. Las reglas de quoting son delicadas; consultaman bash. - Go: usa RE2, así que backreferences y lookarounds no están disponibles. Compromiso: garantía de tiempo lineal.
Cuándo NO usar regex
La famosa frase de Jamie Zawinski de 1997: «Some people, when confronted with a problem, think 'I know, I'll use regular expressions.' Now they have two problems.»
- No parsees HTML / XML con regex. Usa un parser real (DOMParser en navegadores, BeautifulSoup en Python, jsoup en Java, etc.). La estructura anidada de HTML está fundamentalmente más allá de lo que regex puede expresar limpiamente.
- No parsees JSON con regex. Usa JSON.parse / parsers JSON de la biblioteca estándar.
- No valides emails estrictamente con regex. Envía un email de confirmación; ése es el único test fiable.
- No escribas un parser CSV como regex. Los campos entrecomillados con comas embebidas, comillas escapadas y valores multilínea rápidamente se salen de lo que regex maneja limpiamente.
- No intentes hacer match de paréntesis equilibrados. El regex estándar no puede (es un lenguaje libre de contexto); algunos motores PCRE tienen funcionalidades de recursión que hacen trampa, pero un parser real es más limpio.
Errores comunes
- Olvidarse de escapar caracteres especiales.
.,*,?,+,(,),[,],{,},\,^,$,|,/tienen todos significados especiales. Para hacer match literal, prefíjalos con barra invertida. - Cuantificadores codiciosos consumiendo demasiado. Añade
?para matching perezoso cuando quieras la coincidencia más pequeña posible. - Olvidarse del flag global y preguntarse por qué sólo aparece la primera coincidencia. El
String.prototype.match()de JavaScript devuelve sólo la primera coincidencia sin el flagg. - Backtracking catastrófico en inputs largos. Cuantificadores anidados como
(a+)+pueden colgarse en ciertos inputs. Prueba con casos límite. - Suponer que la misma regex se comporta igual en cada lenguaje. Lookbehinds, escapes Unicode y atajos de clase de caracteres varían todos.
- Intentar validar emails demasiado estrictamente. La regex técnicamente correcta RFC 5322 es inmantenible; una regex simple más email-de-confirmación-al-registro es el patrón que funciona.
- Usar regex sobre HTML, JSON o CSV. Usa un parser apropiado; el tiempo que ahorras al principio lo pierdes en bugs.
Más preguntas frecuentes
¿Por qué mi patrón funciona aquí pero falla en mi código?
La causa más común son las diferencias entre motores. El RegExp de JavaScript no soporta algunas funcionalidades que PCRE sí (y viceversa). Trampas comunes: lookbehinds añadidos tarde a JS (ES2018), la sintaxis de grupos con nombre difiere ligeramente, los Unicode property escapes necesitan el flag u, y las clases de carácter POSIX como [[:alpha:]] están casi ausentes en JS. Prueba en el motor en el que vayas a desplegar.
¿Hay una forma «global» de hacer match a través de múltiples líneas?
Dos flags trabajan juntos. El flag m (multilínea) hace que ^ y $ coincidan con el inicio y el final de cada línea en vez de con la cadena entera. El flag s (dotall) hace que . también coincida con caracteres de salto de línea. Combinado con g para global, puedes escribir patrones que abarcan líneas y encuentran cada coincidencia: /^foo.+$/gms.
¿Mis patrones y mi texto de prueba se envían a algún sitio?
No. El matching de patrones usa el motor RegExp JavaScript integrado en el navegador; nada se sube a ningún servidor. Esto importa cuando estás probando patrones contra datos de log de producción reales, respuestas de API internas o contenido sensible.
¿Debería aprender lookbehinds?
Útiles pero no esenciales. Los lookbehinds te permiten hacer match con texto precedido por algo sin incluir ese «algo» en la coincidencia. Ejemplo: (?<=\$)\d+ coincide con dígitos detrás de un signo de dólar sin consumir el signo de dólar. Están soportados en PCRE, JavaScript moderno (ES2018+) y el módulo regex de Python. Si estás escribiendo patrones portables, comprueba primero el motor de destino.
¿Por qué usar (?:...) en lugar de (...)?
Los grupos no capturadores ((?:...)) son ligeramente más rápidos, no toman ranura en el array de capturas y mantienen tus resultados de match limpios. Úsalos cuando necesites agrupación para alternancia o cuantificación pero no necesites extraer el texto coincidente. (http|https):// crea una captura que quizá no necesitas; (?:http|https):// no.
¿Cuál es la forma correcta de hacer match con caracteres Unicode?
En JavaScript, añade el flag u y usa Unicode property escapes: /\p{Letter}+/gu coincide con secuencias de letras en cualquier escritura. Sin el flag u, \w sólo coincide con caracteres de palabra ASCII. El módulo re de Python es Unicode-aware por defecto en Python 3. Java necesita Pattern.UNICODE_CHARACTER_CLASS. La mayoría de los motores tienen alguna forma de ser Unicode-aware; consulta la documentación del tuyo.