Un probador de expresiones regulares te muestra al instante dónde coincide el patrón
Una expresión regular (o regex) es una regla que describe la forma del texto que quieres encontrar. \d{4} significa «cuatro dígitos» y [A-Z][a-z]+ significa «una mayúscula seguida de minúsculas». La regla es corta, pero cambiar un solo símbolo puede alterar mucho lo que encuentra, así que conviene probar el patrón con texto real antes de llevarlo al código.
Esta herramienta ejecuta tu patrón con el motor de expresiones regulares de JavaScript del navegador que estás usando. Las coincidencias se resaltan en el texto, los grupos de captura se distinguen por color y se convierten en columnas de la tabla de coincidencias, y el patrón se desglosa en partes con una explicación sencilla de cada una. Por eso también sirve para entender una regex escrita por otra persona.
Por qué probar una regex antes de llevarla al código
Una regex puede fallar de dos maneras. Puede dejar pasar algo que debería encontrar (una comprobación de teléfono rechaza 612345678 porque espera espacios) o puede aceptar algo que no debería (un patrón de fecha admite 2026-13-45). Ninguno de los dos casos es un error de sintaxis, así que el navegador no avisa de nada. La comprobación más fiable es probar a la vez ejemplos que deben coincidir y ejemplos que no.
El tercer problema es la velocidad. El 2 de julio de 2019, Cloudflare desplegó una regex nueva en una regla de su cortafuegos de aplicaciones web (WAF). El retroceso (backtracking) se disparó, la CPU dedicada a servir HTTP se acercó al 100 % y el servicio estuvo caído 27 minutos. Según el informe que publicó la empresa, la causa fue un fragmento pequeño de un patrón largo: .*(?:.*=.*). Dos patrones que encuentran el mismo texto pueden diferir en cientos de veces en número de pasos, así que prueba con textos de longitud realista.
Probar una regex antes de usarla ayuda en situaciones como estas.
- Validar entradas: al decidir las reglas de teléfono, correo o contraseña de un formulario de registro, escribe en líneas distintas los ejemplos que deben pasar y los que deben bloquearse.
- Extraer valores: al sacar fechas, números de pedido o direcciones IP de registros, archivos CSV o una tabla copiada, comprueba que los valores de los grupos se separan bien. La tabla de coincidencias se puede pegar directamente en una hoja de cálculo.
- Reemplazos masivos: antes de ejecutar buscar y reemplazar en un editor o en el código, mira qué partes cambian y cómo queda el resultado.
- Leer la regex de otra persona: descubre qué busca un patrón de código antiguo, parte por parte, y comprueba si tiene alguna forma que pueda volverse lenta.
Cómo se usa
- Escribe la regex en el campo Patrón, sin las barras de los extremos. Si pegas un literal completo como
/abc/gi, la herramienta lo separa en patrón e indicadores. - Activa los indicadores con los botones de letra de al lado. Activa
gpara encontrar todas las coincidencias. - Pega tu texto en Texto de prueba. Las coincidencias se resaltan al momento y la línea de estado de arriba indica cuántas hay.
- Para un patrón de validación (
^…$), activa Probar cada línea y escribe un ejemplo por línea. Las líneas que pasan llevan ✓ y las que no, ✗. - En la tabla de coincidencias verás los valores de los grupos; al pulsar el número de una fila, esa coincidencia parpadea en el texto. En la pestaña Reemplazar escribes el texto de reemplazo y ves el resultado. La pestaña Código te da JavaScript para llevarte.
Cómo leer el desglose del patrón
El desglose divide el patrón en las unidades que lee el motor. Cada celda muestra arriba los símbolos originales y abajo su significado. Un cuantificador (+, {4}, etc.) se une a la celda anterior para leerlos juntos, como en «dígito 0–9, 4 veces». La barra de color bajo una celda indica el grupo de captura al que pertenece, y ese mismo color se usa en el subrayado del grupo en el texto y en el encabezado de columna de la tabla de coincidencias. Las celdas con borde discontinuo son grupos sin captura, anticipaciones, retrospectivas y «o».
| Celda | Significado | Color de grupo |
|---|---|---|
(?<y> | Inicio del grupo y (grupo 1) | Color 1 |
\d{4} | Dígito 0–9, 4 veces | Color 1 |
) | Fin del grupo y | Color 1 |
- | Un guion, tal cual | Ninguno |
(?<m> \d{2} ) | Grupo m: dígito, 2 veces | Color 2 |
Una celda con borde naranja marca una forma que puede hacer la búsqueda muy lenta: una repetición dentro de otra repetición, como (a+)+, o la misma repetición dos veces seguidas, como .*.*. Una celda roja señala el lugar de un error de sintaxis cuando el navegador rechaza el patrón.
Sintaxis habitual
La columna «Encuentra» de la tabla se obtuvo ejecutando cada texto de ejemplo con el mismo motor de JavaScript que usa esta herramienta.
| Símbolo | Significado | Patrón de ejemplo | Texto de ejemplo | Encuentra |
|---|---|---|---|---|
\d | Un dígito, 0–9 | \d+ | Piso 102B | 102 |
\w | Una letra (A–Z, a–z), un dígito o un guion bajo | \w+ | usuario_01 hola | usuario_01, hola |
. | Cualquier carácter salvo el salto de línea | a.c | abc a-c a↵c | abc, a-c |
[ ] | Uno de los caracteres de dentro, - indica un rango | [A-Z][a-z]+ | Roberin Herramientas | Roberin, Herramientas |
[^ ] | Un carácter que no esté dentro | [^0-9]+ | 612-3456 | - |
^ $ | Inicio y fin del texto (o de la línea) | ^\d+$ | 2026 | 2026 |
{n,m} | La celda anterior, de n a m veces | \d{2,3} | 1 22 333 4444 | 22, 333, 444 |
| | O | gato|perro | perros gato | perro, gato |
\b | Límite de palabra (A–Z, a–z, dígitos, _) | \bsol\b | sol solución | sol |
(?= ) | Anticipación: esto debe ir detrás (esos caracteres no forman parte de la coincidencia) | \d+(?= €) | 3 uds 5000 € | 5000 |
(?<= ) | Retrospectiva: esto debe ir delante | (?<=#)\d+ | pedido #30 y 40 | 30 |
\1 | El texto capturado por el grupo 1, una vez más | (\w)\1 | llave cerro | ll, rr |
+? *? | Repetir lo menos posible | <.+?> | <b>x</b> | <b>, </b> |
Qué cambian los 8 indicadores
Un indicador es un ajuste que afecta a todo el patrón. El mismo patrón sobre el mismo texto puede dar resultados distintos según los indicadores.
| Indicador | Qué hace | Patrón · texto de ejemplo | Desactivado | Activado |
|---|---|---|---|---|
g | Sigue buscando tras la primera coincidencia y las encuentra todas | a · a a a | a | a, a, a |
i | Trata mayúsculas y minúsculas como iguales | abc · ABC | ninguna | ABC |
m | ^ y $ coinciden en cada línea | ^\d · 1↵2 | 1 | 1, 2 |
s | . también coincide con el salto de línea | a.b · a↵b | ninguna | a↵b |
u | Lee los emoji y caracteres similares como un solo carácter y permite usar \p{…} | . · 😀 | 2 mitades | 😀 |
v | Añade a u la resta (--) y la intersección (&&) de conjuntos | [\p{L}--[a-z]] · aZñ | error | Z, ñ |
y | Solo coincide si continúa justo donde terminó la última coincidencia | \d · 12a3 (con g) | 1, 2, 3 | 1, 2 |
d | Devuelve también el inicio y el fin de cada grupo (indices) | Las coincidencias son las mismas. Esta herramienta calcula siempre las posiciones, sean cuales sean los indicadores, y las usa en la tabla de coincidencias. | ||
u y v no pueden estar activados a la vez. Al activar uno, la herramienta desactiva el otro y lo indica en la línea de estado. La sintaxis más reciente, como el indicador v o los modificadores del tipo (?i:…), puede dar un error de sintaxis en un navegador antiguo.
Grupos de captura, grupos con nombre y referencias hacia atrás
Todo lo que va entre paréntesis ( ) se convierte en un grupo de captura, que se guarda por separado dentro de la coincidencia. Los grupos se numeran 1, 2, 3 según el orden de sus paréntesis de apertura, y un grupo como (?<y>…) tiene número y nombre. Si solo necesitas agrupar sin guardar, usa (?:…). Un grupo sin captura no ocupa número, así que los números de los grupos posteriores no cambian.
Para buscar de nuevo el texto que capturó un grupo anterior, usa una referencia hacia atrás: \1 o \k<nombre>. (\w)\1 encuentra el mismo carácter dos veces seguidas. Ten en cuenta también que, si un grupo se repite ((\d)+), solo se conserva el valor de la última repetición. En la tabla de coincidencias, un «—» indica que el grupo no participó en esa coincidencia (el grupo 1 de (a)|(b) cuando coincide b), y «vacío» indica que el grupo coincidió con una cadena vacía.
Símbolos que puedes usar en el texto de reemplazo
La pestaña Reemplazar sigue las mismas reglas que String.prototype.replace de JavaScript. La tabla usa el texto «Pedido 2026-10-22 enviado» con el patrón (\d{4})-(\d{2})-(\d{2}).
| Símbolo | Significado | Texto de reemplazo | Resultado |
|---|---|---|---|
$1–$99 | Grupo numerado | $3.$2.$1 | Pedido 22.10.2026 enviado |
$<nombre> | Grupo con nombre (si el patrón tiene nombres) | $<d>/$<m> | Pedido 22/10 enviado |
$& | Toda la coincidencia | [$&] | Pedido [2026-10-22] enviado |
$` | Todo el texto anterior a la coincidencia | ($`) | Pedido (Pedido ) enviado |
$' | Todo el texto posterior a la coincidencia | ($') | Pedido ( enviado) enviado |
$$ | Un $ literal | $$1 | Pedido $1 enviado |
\n | No es un salto de línea: son los caracteres \ y n | $1\n$2 | Pedido 2026\n10 enviado |
Un número mayor que la cantidad de grupos ($7) se queda como texto literal, y $0 también, porque no es un grupo. Para meter un salto de línea, pulsa Intro en el campo del texto de reemplazo. En el código, usa "\n" dentro de la cadena.
Tildes, la eñe y otras letras
En JavaScript, \w y \b consideran «caracteres de palabra» solo las letras A–Z y a–z, los dígitos y el guion bajo. Eso sigue siendo así con el indicador u activado. Por eso \w+ parte «café» en caf y deja fuera la última letra, y \bcafé\b no encuentra la palabra, porque entre é y un espacio no hay límite de palabra. [A-Za-z] tiene la misma limitación. Para el español hay dos soluciones: enumerar las letras ([a-záéíóúüñ], junto con el indicador i para las mayúsculas) o usar la propiedad Unicode \p{L}, que abarca las letras de cualquier escritura y necesita el indicador u.
| Patrón | Encuentra | Notas |
|---|---|---|
\w+ | A, o, caf, abc, 2026 | Se corta en ñ y é, e incluye dígitos |
[a-z]+ (i) | A, o, caf, abc | Solo letras sin tilde |
[a-záéíóúüñ]+ (i) | Año, café, abc | Letras del español; con i también valen las mayúsculas |
[A-Za-zÀ-ÿ]+ | Año, café, abc | Rango acentuado de Latin-1, más amplio que el español |
\p{L}+ (u) | Año, café, abc | Letras de cualquier escritura |
\bcafé\b | ninguna | \b no considera la é un carácter de palabra |
(?<![\p{L}\d_])café(?![\p{L}\d_]) (u) | café | Con anticipación y retrospectiva, el límite lo defines tú |
El rango À-ÿ va de U+00C0 a U+00FF, así que también contiene el signo de multiplicación × y el de división ÷. Conviene saber además que una letra puede guardarse de dos formas: como un solo carácter (é) o como e más un acento combinado. \p{L}+ se detiene en el acento combinado porque esa marca no es una letra; usa [\p{L}\p{M}]+ si tu texto puede contener la segunda forma. La eñe y las vocales con diéresis (ü) funcionan igual que las demás letras de esa lista. Los signos de apertura ¿ y ¡ no son letras: ninguno de los patrones de la tabla los incluye.
Probar cada línea frente al indicador m
El indicador m comprueba todo el texto de una vez y hace que ^ y $ coincidan al principio y al final de cada línea. Por eso una coincidencia puede cruzar líneas (\s también acepta el salto de línea) y el resultado es solo un recuento de coincidencias. Probar cada línea corta el texto en líneas y comprueba cada una como un texto independiente. Ninguna coincidencia cruza una línea, cada línea recibe un pase (✓) o un fallo (✗), y la línea de estado dice algo como «Pasan 3 de 6 líneas». Cuando pruebas un patrón que debe validar un valor de entrada completo, como en un formulario de registro, probar cada línea equivale a lo que ocurre en el uso real. Reemplazar también trabaja línea por línea y vuelve a unirlas después.
Patrones lentos y el límite de 1 segundo
El motor de expresiones regulares de JavaScript busca una forma de que el patrón coincida y, cuando una elección falla, retrocede y prueba otro camino (backtracking). Un patrón en el que varias repeticiones pueden repartirse los mismos caracteres prueba todos los repartos cuando el texto no coincide. El informe de Cloudflare, al describir la parte problemática del patrón de forma simplificada como .*.*=.*, explicó que x=x coincide en 23 pasos, que un texto con 20 x detrás de x= necesita 555 pasos para coincidir y que 20 x sin = necesitan 4.067 pasos para fallar. Con un solo ; al final, .*.*=.*;, el texto con 20 x detrás de x= falla después de 5.353 pasos. Con una repetición dentro de otra, como (a+)+$, el número de intentos se duplica aproximadamente con cada carácter más.
Esta herramienta ejecuta el patrón en un proceso aparte (un Web Worker) y, si no ha terminado en 1 segundo, finaliza la tarea y te avisa. La página no se congela. Lo más probable es que la causa sean las celdas naranjas del desglose. Hay normalmente tres formas de arreglarlo.
- Quita la repetición dentro de la repetición. En lugar de
(\w+\s?)+$, escribe\w+(?:\s\w+)*$, de modo que cada repetición tenga que incluir un carácter distinto (aquí, un espacio). - Usa un conjunto que excluya el carácter de parada en lugar de
.*. Si cambias.*.*=.*por[^=]*=.*, encuentra el mismo texto casi sin nada a lo que retroceder. - Une las alternativas que pueden dividir el mismo texto de varias maneras.
(\d|\d\d)+$prueba todas las formas de cortar una serie de dígitos en trozos de una y dos cifras, mientras que\d+$termina de una sola pasada.
Diferencias entre lenguajes
La sintaxis de las expresiones regulares varía un poco de un lenguaje a otro. Los resultados de esta herramienta siguen a JavaScript, así que revisa las diferencias siguientes cuando lleves un patrón a otro sitio. La tabla se obtuvo ejecutando los ejemplos en Node.js 26, Python 3.14 y PHP 8.5 (PCRE2 10.44); Java se comprobó con la documentación oficial de Java 21.
| Aspecto | JavaScript | Python re | Java | PHP preg_* |
|---|---|---|---|---|
| Grupo con nombre | (?<n>…) | Solo (?P<n>…); (?<n>…) da error | (?<n>…) | (?<n>…), (?P<n>…) |
| Grupo en el reemplazo | $1, $<n> | \1, \g<n> | $1, ${n} | $1, \1, ${1} (los nombres no valen) |
¿\w acepta letras con tilde y la ñ? | No (ni con u) | Sí (por defecto en patrones de cadena; no con re.ASCII) | No (sí con UNICODE_CHARACTER_CLASS) | No (sí con /u) |
Cuantificador posesivo a++, grupo atómico (?>…) | No existe (error de sintaxis) | Sí (desde 3.11) | Sí | Sí |
| Dónde van los indicadores | Letras tras /…/gi | Argumentos como re.I; para encontrar todo, findall o sub | Argumentos como Pattern.CASE_INSENSITIVE | Letras tras el delimitador /…/iu |
También cambia la longitud permitida dentro de una retrospectiva ((?<=…)). JavaScript acepta un patrón de longitud indefinida como (?<=a+). Python solo acepta una longitud fija. PHP, a partir de PCRE2 10.43, acepta patrones con un límite de longitud ((?<=a{1,3}), máximo por defecto de 255 caracteres). El \d de Python considera también dígitos los números de ancho completo «12», mientras que el \d de JavaScript solo reconoce el 0–9.
Errores frecuentes
- Una sola barra invertida al crear el patrón desde una cadena: la cadena de JavaScript
"\d+"se convierte end+. Hay que escribirla dos veces, como ennew RegExp("\\d+"). La línea «Creado desde una cadena» de la pestaña Código muestra el patrón con eso ya resuelto. - Un punto sin escapar:
1.5también coincide con «125». Escribe el punto literal como1\.5. - Llamar varias veces a
test()con una regex con el indicador g: la regex recuerda su última posición (lastIndex), así que los resultados sobre el mismo texto alternan true, false, true. Si solo necesitas un sí o un no, es más seguro dejar g desactivado. - El
.*voraz:<.+>toma todo «<b>x</b>» de una vez. Para tomar las etiquetas una a una, usa<.+?>o<[^>]+>. - Un patrón de validación sobre un texto de varias líneas: sin el indicador m,
^…$trata todo el texto como una sola pieza, así que con varias líneas da 0 coincidencias. Para probar varios ejemplos, activa Probar cada línea. - Querer validar un correo a la perfección con una sola regex: las direcciones que admite el estándar son tan variadas que un patrón sencillo deja fuera algunas o acepta de más. El patrón de correo de los ejemplos es un filtro aproximado; enviar un correo de confirmación es la forma habitual de estar seguro.
Límites
- Los resultados siguen el motor de expresiones regulares de JavaScript del navegador que usas. Los patrones de Python, Java, PHP y de los editores pueden diferir en sintaxis y resultados, como muestra la tabla anterior.
- Los límites son 1.000 caracteres para el patrón, 50.000 para el texto de prueba, 2.000 para el texto de reemplazo y 200.000 para el resultado. La tabla de coincidencias y el resaltado muestran las primeras 1.000 coincidencias; el recuento y el resultado del reemplazo incluyen todas.
- La ejecución se detiene al pasar 1 segundo. En un dispositivo lento, el mismo patrón puede tardar más.
- La marca «puede ser lento» del desglose solo busca formas habituales. Que un patrón no tenga la marca no garantiza que sea rápido con cualquier texto.
- «Línea:col.» de la tabla de coincidencias cuenta posiciones de cadena de JavaScript (UTF-16), por lo que un emoji ocupa dos columnas.
- El patrón y el texto que escribes se procesan solo dentro de tu navegador y no se envían a ningún servidor. Tampoco se guardan en la dirección ni en el almacenamiento, así que al recargar vuelve el primer ejemplo.
Base: la sintaxis y las reglas de reemplazo se comprobaron con la especificación ECMAScript y MDN, y los demás lenguajes con la documentación oficial de Python, Java y PHP y el registro de cambios de PCRE2, el 22 de octubre de 2026. Los ejemplos de las tablas se ejecutaron en Node.js 26 (V8), Python 3.14 y PHP 8.5 con los mismos resultados.
Fuentes
- 01ECMAScript: RegExp (Regular Expression) ObjectsSintaxis y reglas de ejecución de las regex de JavaScript
- 02ECMAScript: GetSubstitutionCómo se tratan $1, $<nombre>, $&, $`, $' y $$
- 03MDN: Regular expressionsIndicadores, modificadores (?i:…), indicador v, grupos con nombre
- 04MDN: String.prototype.replace()Símbolos especiales del texto de reemplazo
- 05MDN: Character class escapeLos caracteres que aceptan \d, \w y \s
- 06Cloudflare: Details of the Cloudflare outage on July 2, 2019Caída de 27 minutos por el backtracking de una regex del WAF, pasos de .*.*=.*
- 07Python: re — Regular expression operations(?P<nombre>…), \g<nombre>, retrospectiva de longitud fija, cuantificadores posesivos en 3.11
- 08Java 21: Pattern\w = [a-zA-Z_0-9] sin UNICODE_CHARACTER_CLASS, cuantificadores posesivos
- 09PHP: preg_replace$n, \n y ${n} en el texto de reemplazo
- 10PCRE2 ChangeLog10.43: retrospectiva de longitud variable con límite (255 por defecto)
- 11Unicode: Latin-1 Supplement (0080–00FF)Letras latinas con tilde del rango À–ÿ
Preguntas frecuentes
¿Puedo pegar las barras y los indicadores junto con el patrón?
El campo del patrón admite solo lo que va entre las barras, y los indicadores se activan con los botones de letra de la derecha. Si pegas un literal completo como /abc/gi, la herramienta lo separa en el patrón abc y los indicadores g e i. Si escribes una barra a mano, se lee como un carácter que buscar.
¿Por qué se resalta un solo sitio si coinciden varios?
Con el indicador g desactivado, la búsqueda se detiene en la primera coincidencia. La línea de estado indica entonces cuántas habría con g activado, así que pulsa el botón g para encontrarlas todas.
¿Por qué \w no reconoce las letras con tilde ni la ñ?
En JavaScript, \w acepta solo A–Z, a–z, dígitos y el guion bajo, incluso con el indicador u. Para el español puedes enumerar las letras con [a-záéíóúüñ] y el indicador i, o usar \p{L} con el indicador u para las letras de cualquier escritura.
¿En qué se diferencia el indicador m de Probar cada línea?
El indicador m comprueba todo el texto de una vez y hace que ^ y $ coincidan en cada línea. Probar cada línea comprueba cada una como un texto independiente y la marca como pase o fallo. Para probar con varios ejemplos un patrón que valida un valor de entrada, conviene Probar cada línea.
¿Cómo meto los valores de los grupos en el texto de reemplazo?
Usa $1, $2 para los grupos numerados, $<nombre> para los grupos con nombre y $& para toda la coincidencia. Los botones de símbolos de la pestaña Reemplazar los insertan en el cursor. \n se inserta como los dos caracteres, no como un salto de línea, así que pulsa Intro para empezar otra línea.
Si el límite de 1 segundo detiene la ejecución, ¿es incorrecto mi patrón?
La sintaxis puede ser correcta y aun así el patrón provocar un retroceso explosivo. Una repetición dentro de otra, como (a+)+, o la misma repetición dos veces seguidas, como .*.*, hace que los intentos crezcan muy rápido en textos largos que no coinciden. Mira las celdas naranjas del desglose, une las repeticiones o usa un conjunto estrecho como [^=]* en lugar de .*.
¿Obtendré los mismos resultados en Python, Java o PHP?
Lo básico es parecido, pero hay diferencias. Python escribe los grupos con nombre como (?P<nombre>…) y su \w también acepta letras con tilde, y en PHP \w las acepta si añades /u. Las referencias a grupos en el reemplazo también cambian, como \1 o ${nombre}. Consulta la tabla «Diferencias entre lenguajes» del artículo.
¿Se envía a algún servidor el texto que escribo?
No. El patrón y el texto se ejecutan solo en un Web Worker dentro de tu navegador y no se guardan en la dirección ni en el almacenamiento. Al recargar vuelve el primer ejemplo.