Introducción a las expresiones regulares en Python

En este tutorial vamos a aprender sobre el uso de expresiones regulares en Python, incluida su sintaxis, y cómo construirlas usando el módulo integrado de Python...

En este tutorial, aprenderemos sobre el uso de expresiones regulares en Python, incluida su sintaxis, y cómo construirlas utilizando módulos integrados de Python. Para hacer esto, cubriremos las diferentes operaciones en el [re módulo] de Python (https://docs.python.org/2/library/re.html), y cómo usarlo en sus aplicaciones de Python.

¿Qué son las expresiones regulares?

Las expresiones regulares son básicamente una secuencia de caracteres que se pueden usar para definir un patrón de búsqueda para encontrar texto. Este "motor de búsqueda" está integrado en el lenguaje de programación Python (y también en muchos otros lenguajes) y está disponible a través del módulo re.

Para usar expresiones regulares (o "regex" para abreviar), generalmente especifica las reglas para el conjunto de posibles cadenas que desea hacer coincidir y luego se hace preguntas como "¿Esta cadena coincide con el patrón?", o "¿Hay una coincidencia para el patrón en alguna parte de esta cadena?".

También puede usar expresiones regulares para modificar una cadena o dividirla de varias maneras. Todas estas operaciones de "orden superior" comienzan haciendo coincidir primero el texto con la cadena de expresión regular, y luego la cadena se puede manipular (como si se dividiera) una vez que se encuentra la coincidencia. Todo esto es posible gracias al módulo re disponible en Python, que veremos más adelante en algunas secciones posteriores.

Sintaxis de expresiones regulares

Una expresión regular especifica un patrón que pretende coincidir con la cadena de entrada. En esta sección, le mostraremos algunos de los caracteres y patrones especiales que puede usar para hacer coincidir cadenas.

Caracteres coincidentes {#caracteres coincidentes}

Las expresiones regulares pueden contener tanto caracteres especiales como ordinarios. La mayoría de los caracteres comunes, como 'A', 'a' o '0', son las expresiones regulares más simples; simplemente se emparejan a sí mismos. También hay otros caracteres especiales que no pueden coincidir entre sí, es decir, ^, $, *, +, ?, {, }, [, ] , \, |, ( y ). Esto se debe a que se utilizan para la funcionalidad de coincidencia de orden superior, que se describe más adelante en esta tabla:

Descripción del metacarácter


* Coincide con el elemento precedente cero o más veces. Por ejemplo, ab*c coincide con "ac", "abc", "abbbc", etc. [xyz]* coincide con "", "x", "y ", "z", "zx", "zyx", "xyzzy", etc. (ab)* coincide con "", "ab", "abab", "ababab", etc. + Coincide con el elemento precedente una o más veces. Por ejemplo, ab+c coincide con "abc", "abbc", "abbbc", etc., pero no con "ac". ? Coincide con el elemento anterior cero o una vez. Por ejemplo, ab?c solo coincide con "ac" o "abc". | El operador de elección (también conocido como alternancia o unión de conjuntos) coincide con la expresión anterior o posterior a este operador. Por ejemplo, abc|def puede coincidir con "abc" o "def". . Coincide con cualquier carácter único (muchas aplicaciones excluyen las líneas nuevas, y exactamente qué caracteres se consideran líneas nuevas depende del estilo, la codificación de caracteres y la plataforma, pero es seguro asumir que el carácter de avance de línea está incluido). Dentro de las expresiones de corchetes POSIX, el carácter de punto coincide con un punto literal. Por ejemplo, a.c coincide con "abc", etc., pero [a.c] coincide solo con "a", "." o "c". ^ Coincide con la posición inicial en la cadena, como la función startsWith(). En las herramientas basadas en líneas, coincide con la posición inicial de cualquier línea. ? Coincide con la posición final de la cadena o la posición justo antes de una nueva línea que finaliza la cadena, como la función endsWith(). En las herramientas basadas en líneas, coincide con la posición final de cualquier línea.

[Crédito a Wikipedia por algunas de las descripciones de expresiones regulares.]{.small}

Métodos de expresiones regulares en Python

Hay varios métodos disponibles para usar expresiones regulares. Aquí vamos a discutir algunos de los métodos más utilizados y también dar algunos ejemplos de cómo se utilizan. Estos métodos incluyen:

  1. re.coincidencia()
  2. investigar()
  3. re.encontrar()
  4. re.dividir()
  5. re.sub()
  6. recompilar()

re.match(patrón, cadena, banderas=0)

Esta expresión se usa para hacer coincidir un carácter o conjunto de caracteres al comienzo de una cadena. También es importante tener en cuenta que esta expresión solo coincidirá al principio de la cadena y no al principio de cada línea si la cadena dada tiene varias líneas.

La siguiente expresión devolverá Ninguno porque Python no aparece al principio de la cadena.

1
2
3
4
5
6
# match.py

import re
result = re.match(r'Python', 'It\'s  easy to learn Python. Python also has elegant syntax')

print(result)
1
2
$ python match.py
None

re.search(patrón, cadena)

Este módulo buscará una coincidencia en cualquier lugar en la cadena dada y devolverá los resultados si los encuentra, y Ninguno si no los encuentra.

En el siguiente código, simplemente estamos tratando de encontrar si la palabra "cachorro" aparece en la cadena "Daisy encontró un cachorro".

1
2
3
4
5
6
7
8
# search.py

import re

if re.search("puppy", "Daisy found a puppy."):
    print("Puppy found")
else:
    print("No puppy")

Aquí primero importamos el módulo re y lo usamos para buscar la aparición de la subcadena "cachorro" en la cadena "Daisy encontró un cachorro". Si existe en la cadena, se devuelve un re.MatchObject, que se considera "verdadero" cuando se evalúa en una sentencia if.

1
2
$ python search.py 
Puppy found

re.compile(patrón, banderas=0)

Este método se usa para compilar un patrón de expresión regular en un objeto de expresión regular, que se puede usar para hacer coincidir usando sus métodos match() y search(), que hemos discutido anteriormente. Esto también puede ahorrar tiempo, ya que el análisis/manejo de cadenas de expresiones regulares puede ser computacionalmente costoso de ejecutar.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# compile.py

import re

pattern = re.compile('Python')
result = pattern.findall('Pythonistas are programmers that use Python, which is an easy-to-learn and powerful language.')

print(result)

find = pattern.findall('Python is easy to learn')

print(find)
1
2
3
$ python compile.py 
['Python', 'Python']
['Python']

Tenga en cuenta que solo se devuelve la cadena coincidente, a diferencia de la palabra completa en el caso de "Pythonistas". Esto es más útil cuando se usa una cadena regex que tiene caracteres de coincidencia especiales.

re.sub(patrón, repl, cadena)

Como sugiere el nombre, esta expresión se utiliza para buscar y sustituir una nueva cadena si se produce el patrón.

1
2
3
4
5
6
# sub.py

import re
result = re.sub(r'python', 'ruby', 'python is a very easy language')

print(result)
1
2
$ python sub.py 
ruby is a very easy language

re.findall(patrón, cadena)

Como ha visto antes de esta sección, este método encuentra y recupera una lista de todas las ocurrencias en la cadena dada. Combina las funciones y propiedades de re.search() y re.match(). El siguiente ejemplo recuperará todas las apariciones de "Python" de la cadena.

1
2
3
4
5
6
# findall.py

import re

result = re.findall(r'Python', 'Python is an easy to learn, powerful programming language. Python also has elegant syntax')
print(result)
1
2
$ python findall.py 
['Python', 'Python']

Nuevamente, usar una cadena de coincidencia exacta como esta ("Python") solo es realmente útil para encontrar si la cadena regex aparece en la cadena dada, o cuántas veces ocurre.

re.split(patrón, cadena, maxsplit=0, flags=0)

Esta expresión dividirá una cadena en la ubicación en la que se produce el patrón especificado en la cadena. También devolverá el texto de todos los grupos en el patrón si se usa una característica avanzada como paréntesis de captura en el patrón.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# split.py

import re

result =  re.split(r"y", "Daisy found a puppy")

if result:
    print(result)
else:
   print("No puppy")

Como puede ver arriba, el patrón de caracteres "y" aparece tres veces y la expresión se ha dividido en todos los casos en los que aparece.

1
2
$ python split.py 
['Dais', ' found a pupp', '']

Usos prácticos de las expresiones regulares

Ya sea que lo sepa o no, usamos expresiones regulares casi a diario en nuestras aplicaciones. Dado que las expresiones regulares están disponibles en casi todos los lenguajes de programación, no es fácil escapar de su uso. Veamos algunas de las formas en que se pueden usar las expresiones regulares en sus aplicaciones.

Construcción de URL

Cada página web tiene una URL. Ahora imagina que tienes un sitio web de Django con una dirección como "http://www.ejemplo.com/productos/27/", donde 27 es el ID de un producto. Sería muy engorroso escribir vistas separadas para que coincidan con cada producto.

Sin embargo, con expresiones regulares, podemos crear un patrón que coincida con la URL y extraiga la ID por nosotros:

Una expresión que coincidirá y extraerá cualquier ID numérico podría ser ^products/(\d+)/$.

  • ^products/ le dice a Django que haga coincidir una cadena que tiene "products/" al comienzo de la URL (donde "comienzo" de la cadena se especifica mediante ^)
  • (\d+) significa que habrá un número (especificado por \d+) y queremos capturarlo y extraerlo (especificado por los paréntesis)
  • / le dice a Django que debe seguir otro carácter "/"
  • $ indica el final de la URL, lo que significa que solo las cadenas que terminan con / coincidirán con este patrón

Validación de direcciones de correo electrónico

Cada sistema de autenticación requiere que los usuarios se registren e inicien sesión antes de que se les permita acceder al sistema. Podemos usar expresiones regulares para verificar si una dirección de correo electrónico proporcionada tiene un formato válido.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# validate_email.py

import re

email = "[correo electrónico protegido]"

if not re.match(re.compile(r'^[correo electrónico protegido][^.].*\.[a-z]{2,10}$', flags=re.IGNORECASE), email):
    print("Enter a valid email address")
else:
    print("Email address is valid")

Como puede ver, esta es una cadena de expresiones regulares bastante complicada. Vamos a desglosarlo un poco usando la dirección de correo electrónico de ejemplo en el código anterior. Básicamente significa lo siguiente:

  • ^[correo electrónico protegido]: Coincide con todos los caracteres desde el principio de la cadena hasta el carácter '@'
    • Matches "[correo electrónico protegido]" from "[correo electrónico protegido]"
  • [^.].*: coincide con todos los caracteres excepto "."
    • Matches "gmail" from "[correo electrónico protegido]"
  • \.[a-z]{2,10}$: coincide con los caracteres del TLD del dominio (con una longitud máxima de 10 caracteres) hasta el final de la cadena
    • Matches ".com" from "[correo electrónico protegido]"

Entonces, como era de esperar, el código coincide con nuestra dirección de ejemplo:

1
2
$ python validate_email.py 
Email address is valid

Validación de números de teléfono

El siguiente ejemplo se utiliza para validar una lista de números canadienses con prefijo:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# validate_numbers.py

import re

numbers = ["+18009592809", "=18009592809"]

for number in numbers:
    if not re.match(re.compile(r"^(\+1?[-. ]?(\d+))$"), number):
        print("Number is not valid")
    else:
        print("Number is valid")
1
2
3
$ python validate_numbers.py 
Number is valid
Number is not valid

Como puede ver, debido a que el segundo número usa un carácter "=" en lugar de "+", se considera inválido.

Filtrado de contenido no deseado

Las expresiones regulares también se pueden usar para filtrar ciertas palabras de los comentarios de las publicaciones, lo que es particularmente útil en publicaciones de blogs y redes sociales. El siguiente ejemplo muestra cómo puede filtrar palabras preseleccionadas que los usuarios no deben usar en sus comentarios.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# filter.py

import re

curse_words = ["foo", "bar", "baz"]
comment = "This string contains a foo word."
curse_count = 0

for word in curse_words:
    if re.search(word, comment):
        curse_count += 1

print("Comment has " + str(curse_count) + " curse word(s).")
1
2
$ python filter.py 
Comment has 1 curse word(s).

Conclusión

Este tutorial ha cubierto lo que se necesita para poder usar expresiones regulares en cualquier aplicación. No dude en consultar la documentación del re módulo, que tiene una gran cantidad de recursos para ayudarlo a lograr los objetivos de su aplicación.