Taller de Expresiones Regulares¶
Esto es el material para un taller de unas de 3 horas donde aprenderás a usar expresiones regulares.
¿Qué son?¶
Las Expresiones regulares (Regular Expressions, regexp, o en adelante regex) son una secuencia de caracteres que definen un patrón de búsqueda. Pero más que un patrón, son como un robot (en realidad un autómata finito) que va revisando, de izquierda a derecha, una cadena de texto que le das, revisando el patrón de caracteres (que es una cadena de texto también). Este patron es el que denominamos una regex. Es decir, siempre tendrás un texto que buscar y un texto especial, que representa un conjunto de caracteres posibles (la cadena regex).
Una expresión regular (regex) es una cadena de texto pero con metacaracteres. Esos caracteres especiales no se comportan como el carácter que dicen ser, sino que definen cierta funcionalidad.
Estos son algunos ejemplos, que espero puedas entender al final del taller:
hola
h.?a
h+b.
^[0-9]+\.[0-9]{2}$
[2-4]?[3-9ag]
aju{2,8}m[-.]z
(ad)+juju.[0-9]?-
(ho|la)?[4-7zu]
([0-4][0-9]|5[0-2])[0-9]{3}
^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+\.[a-zA-Z]{2,}$
^[a-zA-Z0-9_]+$
^[67][0-9]{8}
^[0-9]{2}\/[0-9]{2}\/[0-9]{4}$
^.{3,32}#[0-9]{4}$
^25[0-5]| 2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$
En estos ejemplos ya te puedes hacer una idea de los caracteres normales y los especiales (metacaracteres).
¿Para qué se usan las regex?¶
Su principal uso es :
Buscar, o detectar, patrones en cadenas de texto
Reemplazar partes del texto
¿Dónde se usan?¶
En muchísimas herramientas:
Lenguajes de Programación
Ofimática
Bases de Datos (en SQL)
Editores de texto
IDEs
comandos (grep / awk )
… y más.
Con ligeras variaciones [1] una vez que las aprendes, te adaptas rápidamente a la herramienta que quieras utilizar. Necesitas ver qué funciones necesitas usar y en algunos casos alguna particularidad en el uso de algún caracter especial, o definición de grupos, o algún caso muy complejo. Pero el 99% del aprendizaje es entenderlas como forma genérica de expresar cadenas de texto.
Porque en realidad es un lenguaje de creación de cadenas de texto (por decirlo de alguna forma).
Metacaracteres¶
Una regex contiene:
caracteres normales. Por ejemplo h o l a 1 ; , 5 # @
… y caracteres especiales (metacaracteres). Algunos son: . | ? ( ] +
Estos metacaracteres tienen un significado especial. Y hay varios:
El punto .. Representa cualquier caracter (.) P.ej ab.de
La barra vertical |. Representa alternancia (un or). Uno u otro, sea caracter o expresión. P.ej a|b o padre|madre
Los caracteres cuantificadores ? + * { } se usan para expresar la cantidad de caracteres (o grupos o rangos) que pueden aparecer. Afecta al anterior:
? Indica que el carácter (grupo / rango / …) puede aparecer una o ninguna vez. 0 o 1. P.ej abd?j
+ Indica que aparece al menos una vez. Es decir, una o muchas (¿infinitas?) veces. 1 o N. P.ej abd+j
Puede aparecer o no. Y una vez o muchas. Es decir, 0, 1 o N. P . P.ej abd*j
{n,m} (o variaciones). El anterior aparece un mínimo de n veces y un máximo de m veces. Entre n y m. P.ej. abd{2,5}j
Los corchetes [ ]. Representan:
Un caracter del grupo (uno cualquiera). P. ej [abcd]
Uno de un rango de caracteres. Usando el metacaracter menos -. P.ej [a-d]
Un caracter quen no está en ese grupo. Usando el metacaracter ^. P.ej [^a-d 8y6]
Un caso (importante) especial es el caracter . (punto). [.] es el carácter punto (sin los corchetes es cualquier carácter)
^ $. Representan el caracter «oculto» principio de línea ^ y fin de línea $ . Es decir, no es lo mismo abc (en cualquier parte de la línea) que ^abc$ (una línea con la cadena abc). Ojo al comportamiento especial de ^ dentro de corchetes (ya, un poco confuso).
( ). Representan un grupo de caracteres. Generalmente cada grupo se representa con un número y luego se puede hacer referencia a él (es una de las particularidades en las que fijarse en cada herramienta). Es muy útil y muy potente. Algunos ejemplos sencillos, usando metacaracteres anteriores: (p|m)adre , ([67]){3} 7+ 5
Si quieres verlo con más detalle, pudes revisar Caracteres Especiales . Porque ahora ya podemos ir a revisar las regex del principio y comenzar a entenderlas. Solo queda ponerse a practicar.
Backslash Characters¶
El uso de (backslash) es el habitual para decir que el siguiente caracter es especial. Ocurre en todos los lenguajes de programación.
En regex, como vimos ya existen los metacaracteres. Pero hay más, que son los que se usan con \ (backslash) antes .
\ d (de digit) equivalente a [0-9]
\ w (de word) equivalente a [A-Za-z0-9 _]
\ s (de space) equivalente a [ \ f \ n \ r \ t], espacio en blanco, tabuladores, saltos de línea, etc
Si los usas en mayúsculas son los caracteres «no» word , digit o space. \ D \ W \ S
De todas formas, hasta que te familiarizes un poco, mejor usa los corchetes que es más fácil.
También se usa \ b como caracter «delimitador de palabra» (boundary).
Y además hay varios para representar caracteres ocultos, por ejemplo:
\ t equivalente a un tabulador
\ n equivalente a una nueva linea
Y varios más
Comportamiento¶
Esta suele ser también una de las particularidades de cada herramienta y su forma de implementar las regex en su sistema.
¿La búsqueda distingue mayúsculas de minúsculas? ignorecase
¿Busco en cada línea o en varias líneas a la vez? multiline
¿Soy avaricioso en la búsqueda o no? greedy
¿Como digo que es una regex y no una cadena de texto normal y corriente? Uso de delimitadores
Tutoriales¶
Hay un montón de información disponible, pero lo importante es ponerte a utilizarlo y comprobarlo en la práctica. Aquí te dejo tres referencias interesantes, de menor a mayor dedicación (y complejidad):
El soporte de ayuda de Google , que lo puedes probar directamente en Google Docs
Uno completo en video
Una clase muy completa. En inglés, centrada en Python y por un profesor buenísimo : Week 7 CS50P
Ejercicios genéricos (básicos)¶
Entender Expresiones Regulares genéricas
Hay millones de ejemplos, pero por ponerte 10 ejercicios. ¿Qué cadenas de texto encontrarían las siguientes regexp?
hola
h.?a
h+b.
[2-4]?[3-9ag]
aju{2,8}m[-.]z
(ad)+juju.[0-9]?-
(ho|la)?[4-7zu]
([0-4][0-9]|5[0-2])[0-9]{3} . Códigos Postales España
^.{3,32}#[0-9]{4}$ . Usuario Discord
(b25[0-5]|b2[0-4][0-9]|b[01]?[0-9][0-9]?)(.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3} . Dirección ipv4. b es un delimitador de palabra «boundary».z
Diseñar expresiones regulares
La casuística es infinita, pero vamos a empezar con 10 retos sencillos. Dime qué regex nos ayudarían a detectar:
Palabras con solo letras minúsculas
Números enteros positivos
Palabras que empiecen por mayúscula
Número con dos decimales
Código postal español
Contraseña que tenga sólo letras, números y sígno menos (-)
Teléfono móvil español (sin código internacional)
Fecha en formato ISO-8691
Matrículas españolas (de vehículos)
Email (básico)
Diseñar, probar y copiar a otros¶
Una vez que entiendes cómo se contruyen las regexes puedes ponerte a diseñar, probar y copiar lo que otros han hecho. Con tanto metacaracter, backslash y modificadores, puedes ser un poco complicado. Pero recuerda que el objetivo de regex es tener todo un lenguaje para describir (casi) cualquier texto.
Recuerda que, como en programación, debes empezar desde pasos pequeños y sólidos (que funcionen) para luego ir desarrollando la regex.
Un sitio web para aprender, jugar y probar con diferentes regex flavors es REGEX101. Empieza ahí probando a construir tus regex. Y luego ya puedes revisar muchos ejemplos muy útiles:
Y muchos más en iHateRegex
Regex en PHP¶
En PHP se puede usar de diferentes maneras -> php_regex ( puedes probar )
// Usa como delimitador de la cadena el caracter / // Y además el modificador i (ignorecase) $regex = "/ejemplo/i";
Se pueden utilizar las siguientes funciones:
preg_match($regex, $texto) -> function.preg-match. Devuelve 1 o 0 si encuentra la regex
preg_match_all($regex, $texto) -> function.preg-match-all. Devuelve cuantas veces hay coincidencia
preg_replace($regex, $reeemplazo, $texto) -> function.preg-replace. Devuelve el texto con las sustituciones correspondientes.
Ejemplo de código
<?php $texto = "Mi número de teléfono es 123-456-7890."; $patron = "/[0-9]{3}-[0-9]{3}-[0-9]{4}/"; // Patrón para un número de teléfono if (preg_match($patron, $texto, $coincidencias)) { echo "Número de teléfono encontrado: " . $coincidencias[0]; } else { echo "Número de teléfono no encontrado."; } // Aquí se usa agrupación entre paréntesis // preg_match devuelve 1 y además coloca cada grupo en el array matches // $matches[0] es la cadena completa, y luego viene cada grupo preg_match('/(a)(b)*(c)/', 'ac', $matches); print_r($matches) // Extrae el host del url. Usa como delimitador el caracter @ porque hay caracteres / en la regex preg_match('@^(?:http://)?([^/]+)@i', "http://www.php.net/index.html", $matches); // El uso de ?: dentro de un grupo indica que ese no cuenta (ya, es confuso). Es decir el primer grupo // es el que está en los segundos paréntesis (no en los primeros, porque lleva ?: para indicar que no lo // tengan en cuenta. Por eso el grupo 1 es "cualquier texto que no sea /" $host = $matches[1]; // Usa \d como sustituto de [0-9] . Aquí se devuelve texto reemplazado $textoModificado = preg_replace("/\d{3}-\d{3}-\d{4}/", "XXX-XXX-XXXX", $texto); echo "Texto modificado: " . $textoModificado; ?>
Regex en Javascript¶
Regex ( Expresiones regulares ) son una secuencia de caracteres que define un patrón de búsqueda -> js_regex
Muy útil tanto para buscar como para reemplazar texto (que es el tipo de datos más común en la web)
En JS puedes aprender, diseñar y probar en regexr . Super útil!
Regex en Python¶
(Pendiente documentar)
Notas