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 :

  1. Buscar, o detectar, patrones en cadenas de texto

  2. Reemplazar partes del texto

¿Dónde se usan?

En muchísimas herramientas:

  1. Lenguajes de Programación

  2. Ofimática

  3. Bases de Datos (en SQL)

  4. Editores de texto

  5. IDEs

  6. comandos (grep / awk )

  7. … 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:

  1. caracteres normales. Por ejemplo h o l a 1 ; , 5 # @

  2. … y caracteres especiales (metacaracteres). Algunos son: . | ? ( ] +

Estos metacaracteres tienen un significado especial. Y hay varios:

  1. El punto .. Representa cualquier caracter (.) P.ej ab.de

  2. La barra vertical |. Representa alternancia (un or). Uno u otro, sea caracter o expresión. P.ej a|b o padre|madre

  3. Los caracteres cuantificadores ? + * { } se usan para expresar la cantidad de caracteres (o grupos o rangos) que pueden aparecer. Afecta al anterior:

    1. ? Indica que el carácter (grupo / rango / …) puede aparecer una o ninguna vez. 0 o 1. P.ej abd?j

    2. + 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

    3. {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

  4. Los corchetes [ ]. Representan:

    1. Un caracter del grupo (uno cualquiera). P. ej [abcd]

    2. Uno de un rango de caracteres. Usando el metacaracter menos -. P.ej [a-d]

    3. Un caracter quen no está en ese grupo. Usando el metacaracter ^. P.ej [^a-d 8y6]

    4. Un caso (importante) especial es el caracter . (punto). [.] es el carácter punto (sin los corchetes es cualquier carácter)

  5. ^ $. 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).

  6. ( ). 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 .

  1. \ d (de digit) equivalente a [0-9]

  2. \ w (de word) equivalente a [A-Za-z0-9 _]

  3. \ s (de space) equivalente a [ \ f \ n \ r \ t], espacio en blanco, tabuladores, saltos de línea, etc

  4. 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:

  1. \ t equivalente a un tabulador

  2. \ n equivalente a una nueva linea

  3. 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.

  1. ¿La búsqueda distingue mayúsculas de minúsculas? ignorecase

  2. ¿Busco en cada línea o en varias líneas a la vez? multiline

  3. ¿Soy avaricioso en la búsqueda o no? greedy

  4. ¿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):

  1. El soporte de ayuda de Google , que lo puedes probar directamente en Google Docs

  2. Uno completo en video

  3. 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?

  1. hola

  2. h.?a

  3. h+b.

  4. [2-4]?[3-9ag]

  5. aju{2,8}m[-.]z

  6. (ad)+juju.[0-9]?-

  7. (ho|la)?[4-7zu]

  8. ([0-4][0-9]|5[0-2])[0-9]{3} . Códigos Postales España

  9. ^.{3,32}#[0-9]{4}$ . Usuario Discord

  10. (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:

  1. Palabras con solo letras minúsculas

  2. Números enteros positivos

  3. Palabras que empiecen por mayúscula

  4. Número con dos decimales

  5. Código postal español

  6. Contraseña que tenga sólo letras, números y sígno menos (-)

  7. Teléfono móvil español (sin código internacional)

  8. Fecha en formato ISO-8691

  9. Matrículas españolas (de vehículos)

  10. 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:

  1. Usuario Discord

  2. Usuario genérico

  3. Número telefónico

  4. Dirección Email

  5. Y muchos más en iHateRegex

Regex en PHP

  1. 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";
    
  2. Se pueden utilizar las siguientes funciones:

    1. preg_match($regex, $texto) -> function.preg-match. Devuelve 1 o 0 si encuentra la regex

    2. preg_match_all($regex, $texto) -> function.preg-match-all. Devuelve cuantas veces hay coincidencia

    3. preg_replace($regex, $reeemplazo, $texto) -> function.preg-replace. Devuelve el texto con las sustituciones correspondientes.

  3. 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

  1. Regex ( Expresiones regulares ) son una secuencia de caracteres que define un patrón de búsqueda -> js_regex

  2. Muy útil tanto para buscar como para reemplazar texto (que es el tipo de datos más común en la web)

  3. En JS puedes aprender, diseñar y probar en regexr . Super útil!


Regex en Python

(Pendiente documentar)


Notas