2020-05-12


En este artículo, haremos que tus ojos lloren sangre. De alegría.
Las expresiones regulares (regex o regexp) son extremadamente útiles para extraer información de cualquier texto, buscando una o más coincidencias de un patrón de búsqueda específico (es decir, una cadena específica de caracteres ASCII o unicode).
Los campos de aplicación van desde la validación hasta el análisis/reemplazo de strings, pasando por la traducción de datos a otros formatos y scraping web.
Una de las características más interesantes es que, una vez que aprendas la sintaxis, podrás usar esta herramienta en (casi) todos los lenguajes de programación (JavaScript, Golang, Kotlin, Java, C#, Python, Perl y muchos otros) con muy pocas diferencias en cuanto a características y versiones de sintaxis.
Comencemos examinando algunos ejemplos y explicaciones.
| Regex | Resultado |
|---|---|
| ^Homer | Corresponde a cualquier secuencia que comience con Homer |
| Marge$ | Corresponde a una cadena que termina con Marge |
| ^Bart Simpson$ | Correspondencia exacta de cadena (comienza y termina con Bart Simpson ) |
| Lisa | Corresponde a cualquier cadena que tenga el texto Lisa |
| Regex | Resultado |
|---|---|
| abc* | Corresponde a una cadena que tiene ab seguido de cero o más c |
| abc+ | Corresponde a una cadena que tiene ab seguido de uno o más c |
| abc? | Corresponde a una cadena que tiene ab seguido de cero o un c |
| abc{2} | Corresponde a una cadena que tiene ab seguido de 2 c |
| abc{2,} | Corresponde a una cadena que tiene ab seguido de 2 o más c |
| abc{2,5} | Corresponde a una cadena que tiene ab seguido de 2 hasta 5 c |
| a(bc)* | Corresponde a una cadena que tiene a seguido de cero o más copias de la cadena bc |
| a(bc){2,5} | Corresponde a una cadena que tiene a seguido de 2 hasta 5 copias de la cadena bc |
| Regex | Resultado |
|---|---|
| a(b|c) | Corresponde a una cadena que tiene a seguido de b o c (y captura b o c) |
| a[bc] | Igual al anterior, pero sin capturar b o c |
| Regex | Resultado |
|---|---|
| \d | Corresponde a un solo carácter que es un dígito |
| \w | Corresponde a un carácter de palabra (carácter alfanumérico más guion bajo) |
| \s | Corresponde a un carácter de espacio en blanco (incluye tabulaciones y saltos de línea) |
| . | Corresponde a cualquier carácter |
Usa el . con cuidado, ya que muchas veces la clase o la clase de caracteres negada (que abordaremos a continuación) son más rápidas y precisas.
\d, \w y \s también presentan sus negaciones con \D, \W y \S respectivamente.
Por ejemplo, \D ejecutará la
correspondencia inversa (corresponde a un solo carácter sin dígito)
en relación a la obtenida con \d.

Para ser considerado literalmente, debes escapar los caracteres ^ . [ $ ( ) | * + ? { \ con una barra invertida \, ya que tienen un significado especial. Al escapar el carácter, puedes encontrar
un $ antes de un dígito
.
También es posible encontrar caracteres no imprimibles, como tabulaciones \t, nuevas líneas \n y retornos \r.
Una regex generalmente se escribe en este formato /abc/, donde el patrón de búsqueda está delimitado por dos caracteres de barra /. Al final, podemos especificar una flag con los siguientes valores (que pueden combinarse) =
/aBc/i encontraría AbC)| Regex | Resultado |
|---|---|
| a(bc) | Los paréntesis crean un grupo de captura con el valor bc |
| a(? =bc)* | Usando ? = desactivamos el grupo de captura |
| a(?<foo>bc) | Usando ?<foo> colocamos un nombre al grupo |

Este operador es muy útil cuando necesitamos extraer información de cadenas o datos usando tu lenguaje de programación preferido. Cualquier ocurrencia múltiple capturada por varios grupos será expuesta en forma de un array clásico = accederemos a sus valores especificando un índice en el resultado de la coincidencia.
Si elegimos nombrar los grupos que utilizaremos (como (?<foo>...)), podremos recuperar los valores del grupo usando el resultado de la coincidencia como un diccionario/map donde las claves serán el nombre de cada grupo.
| Regex | Resultado |
|---|---|
| [abc] | Corresponde a una cadena que tiene a o b o c (lo mismo que a|b|c) |
| [a-c] | Lo mismo que el anterior |
| [a-fA-F0-9] | Una cadena que representa un solo dígito hexadecimal, sin distinción entre mayúsculas y minúsculas |
| [0-9]% | Una cadena que tiene un carácter de 0 a 9 antes de un signo de % |
| [^a-zA-Z] | Una cadena que no tiene una letra de a a z o de A a Z . En este caso, el ^ se usa como negación de la expresión |
Recuerda que dentro de las expresiones entre corchetes todos los caracteres especiales (incluida la barra invertida \) pierden sus poderes especiales = por lo tanto, no aplicaremos la regla de escape.

Los cuantificadores * + {} son operadores codiciosos (greedy), por lo que expanden la coincidencia lo máximo posible a través del texto proporcionado.
Por ejemplo, <.+> corresponde a <div>simple div</div> en Esta es una prueba de <div>simple div</div>. Para capturar solo la etiqueta div, podemos usar un ? para hacerlo perezoso (lazy) =
<.+?> corresponde a cualquier carácter una o más veces incluido dentro de < y >, expandiéndose según sea necesario
Ten en cuenta que una mejor solución debe evitar el uso de . en favor de una regex más estricta =
<[^<>]+> corresponde a cualquier carácter , excepto < o > una o más veces incluidos dentro de < y >
\babc\b corresponde a una búsqueda de solo palabras completas
\b representa un ancla como el signo de intercalación (es similar a $ y ^) que coincide con posiciones donde un lado es un carácter de palabra (como \w) y el otro lado no es un carácter de palabra (por ejemplo, puede ser el inicio de la cadena o un carácter de espacio)
Tiene una negación, \B. Es decir, el resultado de todas las posiciones donde \b no coincide y podría estar si queremos encontrar un patrón de búsqueda completamente rodeado por caracteres de palabra.
| Regex | Resultado |
|---|---|
| ([abc])\1 | Usando \1, coincide con el mismo texto que fue coincidido por el primer grupo de captura |
| ([abc])([de])\2\1 | Podemos usar \2 (\3, \4, etc.) para identificar el mismo texto que fue coincidido por el segundo (tercero, cuarto, etc.) grupo de captura |
| (?<foo>[abc])\k<foo> | Colocamos el nombre foo en el grupo y lo referenciamos después (\k<foo>). El resultado es el mismo que el primer regex |
e(?=r) Corresponde a e solo si es seguido por r, pero r no será parte de la coincidencia general de la expresión regular (?<=r)i Corresponde a i solo si es precedido por un r, pero r no será parte de la coincidencia general de la expresión regular
| Regex | Resultado |
|---|---|
| e(?=r) | Corresponde a e solo si es seguido por r, pero r no será parte de la coincidencia general de la expresión regular |
| (?<=r)i | Corresponde a i solo si es precedido por un r, pero r no será parte de la coincidencia general de la expresión regular |
Y al usar el operador de negación =
| Regex | Resultado |
|---|---|
| e(?!r) | Corresponde a e solo si no es seguido por r, pero r no será parte de la coincidencia general de la expresión regular |
| (?<!c)i | Corresponde a i solo si no es precedido por un c, pero c no será parte de la coincidencia general de la expresión regular |

Regex101 es un sitio donde puedes visualizar tus regexes de una forma didáctica. Además de poder exportar fragmentos de código para tu lenguaje favorito.
Hacer tablas en markdown (como este sitio está escrito) es complicado, pero gracias a Markdown Tables la tarea se vuelve más fácil
El poder de la regex no puede ser subestimado, joven saltamontes. Los campos de aplicación de regex pueden ser múltiples y estoy seguro de que has notado al menos una de estas tareas durante tu carrera como desarrollador =
UPDATE = Escribí un nuevo artículo con las regexes más usadas, que puedes ver aquí = Regex útiles para tu día a día