Probador de Regex

Sustituye la entrada actual por datos de demostración.

Resultado esperado: Coinciden dos fechas: 2026-10-02 y 2026-11-15. La sustitución produce: Releases: 02/10/2026, 15/11/2026.

Limitaciones: Usa JavaScript RegExp, no PCRE. El patrón encuentra el formato de una fecha, pero no valida el calendario. El worker tiene un límite de 1,5 segundos.

Nada de lo que escribes aquí se almacena, registra ni comparte.

Escribe un patrón y ve cada coincidencia resaltada mientras escribes, con grupos de captura y posiciones. La búsqueda se ejecuta en un hilo aparte, así que ni un patrón con backtracking catastrófico bloquea la página.

Cómo usarlo

  1. Introduce tu patrón y activa las flags que necesites.
  2. Pega el texto contra el que probar; las coincidencias se resaltan al instante.
  3. Marca Sustituir para previsualizar una sustitución usando $1 o $<nombre>.

Lo que las expresiones regulares no pueden hacer

Una expresión regular busca patrones, no estructura. No recuerda a qué profundidad está dentro de algo, lo que significa que cualquier cosa con anidamiento arbitrario queda realmente fuera de lo que puede expresar: paréntesis equilibrados, comillas anidadas, HTML, JSON, código fuente.

Los patrones que parecen funcionar con esto están acertando en el caso común y fallando en el resto, normalmente sin avisar. El patrón de etiquetas HTML que funciona hasta que un atributo contiene un >. El eliminador de comentarios que se come la mitad de una cadena literal. El divisor de CSV que se rompe en la primera coma entre comillas. Cada uno es un error que aparece meses después con los datos de otra persona.

La regla práctica es que, si lo que buscas puede contenerse a sí mismo, necesitas un parser. Las regex son excelentes en la capa inferior: validar un campo, extraer valores de un formato de log conocido, buscar y reemplazar en todo un código, dividir por un delimitador que no puede aparecer dentro de las partes.

Codicioso, perezoso y de dónde sale el backtracking

Los cuantificadores son codiciosos por defecto: .* toma todo lo que puede y luego devuelve caracteres uno a uno hasta que encaja el resto del patrón. Así, <.+> aplicado a <b>text</b> coincide con toda la cadena y no con la primera etiqueta, porque el .+ codicioso se lo traga todo y el > final se satisface con el último de la entrada.

Añadir un signo de interrogación vuelve perezoso al cuantificador: <.+?> toma lo mínimo posible y coincide solo con <b>. Lo perezoso suele ser lo que la gente quiere decir, y una clase de caracteres suele ser mejor que ambas: <[^>]+> dice exactamente lo que quieres, no puede cruzar el límite de una etiqueta y no hace backtracking.

Ese último punto es la razón práctica para que importe. El backtracking es lo que vuelve lento un patrón, y anidar un cuantificador dentro de otro - (a+)+, (\s*\w+)* - hace que el número de caminos que explora el motor crezca exponencialmente. Con una entrada que casi coincide, un patrón así puede tardar minutos. Este probador ejecuta la búsqueda en un worker y la corta al segundo y medio precisamente porque escribir un patrón así sin querer es de lo más normal.

Diferencias entre dialectos que te pueden morder

El motor que se usa aquí es el de tu navegador, así que los resultados coinciden exactamente con JavaScript. No tienen por qué coincidir con el lenguaje en el que vayas a pegar el patrón.

Los grupos con nombre son (?<name>...) en JavaScript, .NET y PCRE moderno, pero Python también acepta (?P<name>...) y las herramientas antiguas solo entienden esta última forma. El lookbehind está disponible en JavaScript actual, .NET y PCRE, pero en Python debe tener longitud fija y en Go no existe. RE2 de Go y el crate regex de Rust omiten por diseño las referencias hacia atrás y los lookarounds, que es lo que les permite garantizar tiempo lineal: un patrón que dependa de cualquiera de ellos sencillamente no compilará.

El significado de las clases abreviadas también cambia. En JavaScript \d son solo dígitos ASCII, en .NET coincide por defecto con dígitos de cualquier escritura y en Python depende de si el patrón es str o bytes. Y la bandera u de JavaScript es la que hace que . y los cuantificadores trabajen con puntos de código completos en lugar de unidades de código; sin ella, un patrón se rompe con emoji y con cualquier carácter fuera del plano multilingüe básico.

Prueba en tu propio entorno de ejecución antes de desplegar un patrón que importe.

Escribir un patrón que puedas leer más adelante

Ánclalo. Un patrón sin ^ y $ que se usa para validar un campo coincidirá tranquilamente con una subcadena, así que un patrón de correo sin anclas acepta cualquier cosa que tenga una dirección válida escondida dentro. Es una fuente recurrente de validaciones que se pueden saltar.

Prefiere las clases de caracteres a la alternancia cuando ambas funcionen: [abc] es más claro y rápido que (a|b|c), y [^,]+ expresa «no cruza una coma» de una forma que .+? solo aproxima. Pon nombre a los grupos en lugar de contarlos, porque (?<year>...) sobrevive a que alguien inserte un grupo delante y $3 no.

Después, prueba los negativos. La mayoría de patrones se escriben probando entradas que deberían coincidir hasta que una lo hace, lo que produce sin falta algo demasiado permisivo. El ejercicio más útil es pegar las entradas que no deben coincidir y confirmar que no lo hacen: la dirección mal formada, el valor con un delimitador dentro, la línea que es casi, pero no exactamente, el formato de log que esperas.

Leer un patrón real por partes

Toma un patrón para una línea de log habitual: ^(\S+) \S+ \S+ \[([^\]]+)\] "(\w+) ([^"]*)" (\d{3}) (\d+)$. Parece denso y se descompone con limpieza. El acento circunflejo ancla al comienzo de la línea. (\S+) captura una secuencia de caracteres que no son espacio - la dirección del cliente - y los dos \S+ sin captura que siguen se saltan los campos identity y user, que nadie usa.

\[([^\]]+)\] captura la marca de tiempo: un corchete escapado, luego todo lo que no sea un corchete de cierre, y luego el corchete de cierre. La clase negada es lo que vuelve robusto a este fragmento, porque no puede pasarse del final del campo como haría .+. La petición entre comillas es la misma idea aplicada a las comillas, dividida en el método y la ruta.

(\d{3}) captura exactamente tres dígitos para el código de estado y (\d+) captura el número de bytes, con el signo de dólar anclando el final. La lección se generaliza: un patrón construido con clases negadas y conteos explícitos se lee con más claridad y se ejecuta más rápido que el mismo patrón construido con puntos y cuantificadores perezosos.

Retroceso catastrófico y cómo evitarlo

Los motores con retroceso - que son la mayoría - prueban alternativas cuando una coincidencia falla. Anidar un cuantificador dentro de otro le da al motor una cantidad exponencial de formas de dividir la entrada, así que un patrón como (a+)+$ frente a una larga cadena de caracteres a seguida de una b puede ejecutarse durante más tiempo del que lleva existiendo el universo.

Este es un vector real de denegación de servicio, catalogado como ReDoS, y ha tumbado servicios en producción: una expresión regular en la ruta que analiza las peticiones, ante una entrada preparada, deja un núcleo de CPU al máximo de forma indefinida. La caída global de Cloudflare en 2019 se debió exactamente a un patrón con esta forma.

Tres defensas cubren la mayoría de los casos. Evita anidar cuantificadores y prefiere una clase de caracteres negada al punto: [^"]* no puede solaparse con lo que viene después, así que no hay nada a lo que retroceder. Usa grupos atómicos o cuantificadores posesivos donde el motor los admita. Y cuando los patrones vengan de los usuarios, ejecútalos en un worker con tiempo límite, que es lo que hace este probador, o usa un motor de tiempo lineal como RE2.

Unicode y por qué \w no alcanza

Las clases abreviadas se definieron para ASCII y en gran medida lo siguen siendo. En JavaScript, \d solo coincide con 0-9 y \w solo con letras ASCII, dígitos y guion bajo, así que un patrón que valida un nombre con \w+ rechaza José, Zoë y todos los nombres que no se escriben con el alfabeto latino.

Los escapes de propiedades Unicode resuelven esto como corresponde. Con la bandera u, \p{L} coincide con cualquier letra de cualquier sistema de escritura, \p{N} con cualquier carácter numérico y \p{Script=Han} con un sistema de escritura concreto. Son mucho más precisos que ampliar una clase a mano, y siguen funcionando a medida que Unicode agrega caracteres.

Hay un segundo motivo para activar la bandera u: sin ella el motor trabaja con unidades de código UTF-16 en lugar de puntos de código, de modo que un punto coincide con la mitad de un emoji y una clase de caracteres puede partir un par sustituto. Incluso con ella, un carácter visible puede estar formado por varios puntos de código - una bandera, una familia, una letra acentuada escrita como base más marca de combinación -, así que contar caracteres con una expresión regular todavía requiere la notación de conjuntos de la bandera v o una biblioteca que entienda grafemas.

Cuándo no usar una expresión regular

Para cadenas fijas, los métodos de cadena de siempre son más claros y más rápidos: startsWith, includes, split. Recurrir a un patrón para comprobar si una cadena termina en .json es una costumbre que conviene dejar, porque la versión simple no necesita explicación más adelante.

Para cualquier cosa con anidamiento - HTML, JSON, código fuente, paréntesis balanceados - usa un analizador. Una expresión regular no puede contar profundidad, así que todos los patrones que parecen manejar esto solo aciertan con el caso común y fallan en silencio con el resto. La famosa respuesta de Stack Overflow sobre analizar HTML con expresiones regulares es graciosa porque el argumento de fondo es exacto.

Para datos estructurados casi siempre hay una herramienta hecha a propósito: un analizador de CSV que entiende las comas entre comillas, un analizador de URL que entiende userinfo y puertos, una biblioteca de fechas que entiende zonas horarias. Cada una existe porque la versión con expresión regular se escribió miles de veces y todas las veces estaba sutilmente mal.

Patrones que usarás una y otra vez

Recortar y normalizar espacios: sustituir \s+ por un solo espacio colapsa las secuencias, y ^\s+|\s+$ recorta los extremos cuando el lenguaje no tiene una función trim. Extraer un valor entre comillas: "([^"]*)". Dividir por un delimitador que no aparece dentro de los campos: una clase negada en lugar de un punto perezoso.

Hay dos patrones que conviene no escribir. Validar correos electrónicos con una expresión regular es una trampa: la gramática de la RFC 5322 es genuinamente compleja, y la comprobación pragmática es una parte local no vacía, una arroba y un punto en el dominio, seguidos del envío de un mensaje de confirmación, que es la única validación real. La validación de URL tiene la misma clase de problema, y hoy todos los lenguajes incluyen un analizador de URL que responde bien a esa pregunta.

Cuando un patrón es lo bastante largo como para necesitar explicación, usa grupos con nombre y, en los lenguajes que lo permiten, la bandera extendida que admite espacios y comentarios dentro del patrón. Un patrón que puedas leer dentro de seis meses vale dos líneas de más hoy.

Preguntas frecuentes

¿Qué es el backtracking catastrófico?
Ciertos patrones tardan un tiempo exponencial con entradas que casi coinciden. La forma clásica es un cuantificador dentro de otro, como (a+)+$ probado contra una larga sucesión de caracteres a seguida de otra cosa: el motor prueba todas las divisiones posibles antes de rendirse. Segundos o minutos de CPU bloqueada es un resultado normal.
¿Por qué esta herramienta no se bloquea cuando eso pasa?
Una expresión regular en ejecución no se puede cancelar desde JavaScript, así que la búsqueda ocurre dentro de un Web Worker. Si supera 1,5 segundos, el worker se termina y otro nuevo ocupa su lugar. La página sigue respondiendo y se te explica qué ha pasado.
¿Qué hacen las flags?
g busca todas las coincidencias en lugar de solo la primera, i ignora mayúsculas y minúsculas, m hace que ^ y $ coincidan en los saltos de línea, s permite que . coincida con un salto de línea, u activa el tratamiento Unicode completo incluidos los escapes de propiedad \p{...}, e y ancla la búsqueda en la posición actual.
¿Cómo referencio los grupos de captura al sustituir?
Usa $1, $2 y así para los grupos numerados, $<nombre> para los nombrados, $& para la coincidencia completa y $$ para un signo de dólar literal.
¿Usa el mismo motor que mi código?
Usa el motor JavaScript de tu navegador, así que los resultados coinciden exactamente con JavaScript. PCRE, Python, Go y .NET difieren en el soporte de lookbehind, en la sintaxis de grupos nombrados y en el tratamiento de Unicode, así que verifica en tu propio runtime antes de confiar en un patrón.
¿Se envían mis datos de prueba a alguna parte?
No. Tanto el patrón como el texto se quedan en tu navegador, lo que lo hace seguro para logs y muestras de producción.

Última actualización:

Referencias

MDN — JavaScript RegExp

Cambios recientes

  • — Se añadieron un ejemplo ejecutable, resultados esperados, limitaciones y referencias.

Informar de un problema

Incluye los pasos, el resultado esperado y el real. Elimina secretos y datos personales.

Herramientas relacionadas