Expresiones regulares: qué son,  cómo se usan y ejemplos

Curso de Expresiones Regulares

Toma las primeras clases gratis

COMPARTE ESTE ARTÍCULO Y MUESTRA LO QUE APRENDISTE

Las expresiones regulares son patrones que usaremos para encontrar una o varias combinaciones de caracteres en un texto. Esta, sin embargo, es una definición incompleta. Hoy iremos más allá.

Conocerás por qué RegEx como tal no existe, qué tiene que ver RegEx con un problema profundo de las matemáticas, cómo se relaciona eso con un millón de dólares y vamos a terminar construyendo un chatbot usando únicamente expresiones regulares.

¿Te interesa? Empecemos:

¿Qué es RegEx?

Antes de empezar, definamos adecuadamente el término. RegEx como tal no existe. Hablar de expresiones regulares es como hablar de SQL. No existe un único SQL, sino que todo el mundo toma un poco de él para usarlo a su manera y, aunque sí encontramos similitudes entre PostgreSQL, MySQL y Microsoft SQL, al final son cosas distintas.

Una expresión regular es un conjunto de caracteres que forman un patrón. Este patrón sirve para buscar y comparar strings (. Encontrado el patrón, es posible usar un segundo patrón para remplazar los strings encontrados de ser necesario.

¿Puedes darme un ejemplo?

Esto es una expresión regular, esta simple palabra ya se considera un patrón válido.

hello

Vamos por otro ejemplo de RegEx: imaginemos que tengo un bot de telegram un poquito básico y quiero detectar si una frase empieza por “hola”. Todo lo que tendría que hacer es agregarle a la anterior expresión un ^. Quedaría de esta manera:

^hello

Con este simple cambio, ya la expresión regular se comporta más como queremos. Podemos ir agregando cosillas hasta llegar a la expresión final, o podemos quedarnos con la expresión aproximada (que a veces funciona mejor, ya te lo explico).

Ahora surgen dos dudas:

  1. Por qué usar un RegEx y no usar un simple startswith (de python)
  2. ¿Cómo funciona esto por dentro?

Voy a responder ambas preguntas en un mismo argumento. Hay dos razones por las que usar expresiones regulares es preferible a startswith. La primera, más obvia, es que regex es un caso general. Con ellas podemos crear patrones loquísimos (que ya veremos).

La segunda, el tiempo: mientras que en Python tenemos que leer línea por línea y para aplicarle startswith, con regex lo podemos lograr para todo el texto en una sola sentencia. Entonces, por ese lado, RegEx wins.

Trascendencia de las expresiones regulares: ¿por qué son importantes?

Ahora, mencioné que RegEx era un caso general, ¿verdad? Un RegEx puede ser expresado en forma de máquina de estados y eso cambia totalmente el juego.

Las máquinas de estado son la cosa más increíble que tenemos como humanidad, pero no quiero nerdear sobre máquinas de estados (por hoy), quiero nerdear sobre RegEx. ¿Recuerdan el RegEx ‘^hola’? Ese RegEx lo podemos representar como la siguiente máquina:

state_machine.png

Si miramos con estos ojos a las expresiones regulares, estoy muy seguro de que lo vas a entender mejor. ¿Hasta dónde llega esto? Bueno, les presento a este tipo, que en su video nos enseña cómo gastar 9.5k USD en AWS… Digo, resolver Pokemon con una sola expresión regular. No tiene desperdicio.

Lo que me lleva a preguntarme, ¿es posible expresar toda la computación a partir de expresiones regulares? La respuesta es… No tengo la menor idea. Un grupo de personas estamos intentando extender RegEx a Turing completo, pero hay mucha discusión sobre si YA es Turing completo. Dejo esto sobre la mesa y paso a otro tema porque caso contrario no avanzaremos.

Volviendo a las RegEx

Dejaré por aquí una tabla de trucos para las expresiones regulares. Si vas poco a poco generando máquinas de estado más complejas, acabarás por entender todo y volverte un RegEX master, pero aquí vamos con algunas, las más útiles e interesantes.

cheat_sheet.png

¡Quiero más ejemplos de RegEx!

Vamos por un ejemplo sencillo: vamos a identificar correos electrónicos

  1. Primero intentemos detectar todo, según mi tablita de códigos, punto (.) equivale a cualquier carácter, empezamos por ahí:
.
  1. Listo, es un poco sencillo, pero funciona. Todos los correos tienen @ así que, ¿por qué nuestro regex no iba a tener uno? Si lo acomodamos, queda así:
.@.
  1. Esto detecta el arroba y los dos caracteres junto a él, vamos progresando. Ahora quiero que detecte todos los caracteres que hay junto al arroba. Si miro mi tablita de códigos me doy cuenta de que hay algo que dice 1 o más, a ver si me sirve:
.+@.+
  1. Súper, ya se ve mucho mejor. Vamos por el punto del .com. Hay un problema y es que el caracter de punto representa cualquier caracter. Entonces, ¿cómo digo que necesito específicamente un punto? Lo escapo con ‘\’:
.+@.+\..
  1. Ahora, el dominio. Vamos a cortarlo, no queremos un dominio de más de 3 caracteres. Podemos cortarlo con las llaves {n,m}, eso nos da un rango máximo y un rango mínimo. Quedaría así.
.+@.+\..{2,3}
  1. Hay algo curioso y es que hay muchos más casos, subdominios, no queremos espacios, caracteres especiales (excepto por algunas excepciones), entre otros. Además, no hemos hablado de IPs. Vamos, un lío completo. Lo más importante de todo es saber cuándo parar. Podemos acabar con esto:
(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])

Este es un RegEx para correos electrónicos que funciona en el 99.99% de los casos, pero no es ni usable, ni mantenible, ni nada.

Más ejemplos: vamos a hacer el chatbot más soso de la vida

Esto nos servirá para entender el tema de los reemplazos, uno de los usos más interesantes de RegEx. Imaginemos que yo saludo a mi bot y le digo, “Hola, soy Hector”. Esto lo puedes probar en cualquier editor de RegEx, como Visual studio code o algún otro IDE.

  1. Quiero hacer match, así que mi regex va a ser algo como:
Hola, soy .+
  1. Esto hará que, sea cual sea mi nombre, sea detectado. Pero hay algo más interesante. Si yo hago un agrupamiento del nombre, es decir le pongo paréntesis, así:
Hola, soy (.+)
  1. Entonces pasan cosas interesantes, como que esa información que está entre paréntesis se mueve al replace, usando $1. Es decir, si yo pongo en el replace: $1 “Hola, soy Hector”, se va a remplazar con “Hector” entonces, si yo cambio el replace por
Mucho gusto $1 ¿Cómo te va?

Entonces el bot va a responder Mucho gusto Hector ¿Cómo te va? ¡y ya tenemos un bot que nos saluda!
Podemos tener tantos agrupamientos como queramos y podemos incluso ponerles nombre, pero eso ya está en la guía de trucos.

Último ejemplo: webscraping ultra rápido

Una última para los colegas de Data Science. Usualmente para web scraping usamos librerías como Beautifulsoup, pero con RegEx puedes sacar información mucho más rápido de una página html simplemente con esta sentencia, con la que podemos extraer el título de un blogpost o una noticia:

<h1 .+>(.+)</h1>

El mejor truco para aprender expresiones regulares

Practica. En este artículo no hemos visto aún todas las peculiaridades de RegEx, pero ya tienes lo más importante: curiosidad e intuición para seguir aprendiendo por tu cuenta. Aquí en Platzi tenemos el mejor Curso de Expresiones Regulares de todos. ¡Ve a verlo y nunca pares de escribir expresiones regulares!

Curso de Expresiones Regulares

Toma las primeras clases gratis

COMPARTE ESTE ARTÍCULO Y MUESTRA LO QUE APRENDISTE

0 Comentarios

para escribir tu comentario

Artículos relacionados