Mi regex funciona en el tester pero no en mi código — por qué

El patrón casi nunca es el problema. Es el escapado, los flags o un motor de regex distinto — y cada uno tiene un síntoma característico que te dice ante cuál de los tres estás.

Construyes un patrón en un tester online, encaja perfectamente, lo pegas en tu código y no encaja con nada. La regex no ha cambiado, así que ha cambiado algo a su alrededor. En la práctica es una de tres cosas: el patrón se destrozó al escaparlo dentro de una cadena, los flags no viajaron con él, o tu lenguaje usa un motor de regex distinto al del tester.

Escapado: el patrón de tu código no es el que escribiste

Esta es con diferencia la causa más común, y ocurre siempre que la regex vive dentro de una cadena en vez de en un literal de expresión regular. En una cadena, la barra invertida es en sí misma un carácter de escape, así que se consume antes de que el motor de regex llegue a verla. Tu \d se convierte en una simple d, y \. se convierte en un punto literal que ahora encaja con cualquier carácter. El patrón que recibe el motor es genuinamente distinto del que tecleaste. La solución varía según el lenguaje: en JavaScript usa la forma literal /\d+/ mejor que new RegExp("\\d+"); en Python usa una cadena cruda, r"\d+"; en Java y C# tienes que duplicar cada barra invertida, o usar las cadenas verbatim @"..." de C#.

Los flags se configuran aparte y no se copian

Los testers online ponen los flags en su propia casilla junto al patrón, así que cuando seleccionas y copias, te llevas el patrón y dejas los flags atrás. Tres importan especialmente. El flag m cambia el significado de ^ y $ de "principio y final de toda la cadena" a "principio y final de cada línea" — sin él, un patrón que funcionaba contra un bloque de texto de prueba de varias líneas fallará. El flag s permite que . encaje con saltos de línea, cosa que por defecto no hace. Y el flag i de insensibilidad a mayúsculas es el que más a menudo se olvida que estaba activado.

El flag g tiene su propia trampa

En JavaScript, una regex con el flag g tiene estado: mantiene una propiedad lastIndex que avanza tras cada coincidencia. Si reutilizas ese mismo objeto regex con .test() dentro de un bucle, obtienes resultados alternos de true y false para la misma entrada, lo que parece indeterminismo y es exasperante de depurar. O creas la regex de nuevo cada vez, o quitas el flag g cuando solo necesitas un booleano, o reinicias lastIndex a cero entre llamadas.

No todos los motores hablan el mismo dialecto

La mayoría de testers online usan PCRE por defecto, el dialecto compatible con Perl. Puede que tu código no lo use. Las aserciones lookbehind, los grupos con nombre y los cuantificadores posesivos varían en soporte. El ejemplo más extremo es RE2, que usan Go y varias bases de datos, y que omite deliberadamente las retrorreferencias y el lookahead por completo para que el tiempo de coincidencia se mantenga lineal — un patrón que dependa de eso no es que falle, es que ni siquiera compila. Si tu tester tiene selector de motor, ponlo en tu lenguaje real antes de empezar a construir el patrón, no después de que se rompa.

Coincidencia parcial frente a coincidencia completa

Los testers casi siempre te muestran resaltada cada coincidencia parcial dentro del texto, pero muchas APIs de lenguaje hacen una pregunta distinta. El matches() de Java exige que el patrón consuma la entrada entera, mientras que find() busca una coincidencia en cualquier posición — así que un patrón que se resalta alegremente en un tester devuelve false desde matches(). Python tiene la misma división en tres entre re.match, re.search y re.fullmatch. Si tu patrón parece correcto pero devuelve false, comprueba cuál de esos llamaste antes de tocar la regex.

El paso de depuración que lo encuentra más rápido

Imprime el patrón compilado en tiempo de ejecución — no la línea del código fuente, sino el valor real que recibió el motor. En JavaScript es String(miRegex), en Python print(patron.pattern). Si lo que ves difiere de lo que escribiste, es un problema de escapado y lo has encontrado en un solo paso. Si coincide exactamente, el problema son los flags o el dialecto, y has eliminado dos tercios de las posibilidades sin adivinar.

Nuestro tester de regex muestra el patrón, los flags y las coincidencias uno al lado del otro, y resalta los grupos mientras escribes, para que puedas confirmar la combinación exacta de patrón y flags antes de llevarla a tu código. Funciona en tu navegador, así que puedes probar con datos reales sin riesgo.

→ Probador de Regex