Nota: Puedes ejecutar este post en Google Colab o Binder o verlo en GitHub, pulsa el icono.

Conceptos básicos:

Expresiones regulares (RegEx) es un pequeño lenguaje que usa cadenas de caracteres para encontrar patrones o sustituir caracteres dentro de un texto.

Están integrados en multitud de aplicaciones y lenguajes de programación facilitando enormemente el trabajo con textos.

En python tenemos el módulo re. Para usarlo introducimos lo siguiente:

import re 

Definimos un patrón y una cadena donde buscarlo:

patron="dos"
cadena = "dos"

Se crea un objeto expresión regular y se busca en la cadena de texto

re_object = re.compile(patron)
print(re_object.search(cadena))
<re.Match object; span=(0, 3), match='dos'>

r

Sirve para manejar caracteres especiales (sólo en Python):

    - r"\n" -> equivale a los caracteres \ y n<br>
    - "\n"  -> equivale a salto de línea
print (r"Aquí uso 'r' \n")
print ("\n Aquí no uso 'r' \n y tenemos  \n el salto")
Aquí uso 'r' \n

 Aquí no uso 'r' 
 y tenemos  
 el salto

A la hora de buscar patrones, tenemos diferentes metodos en re, entre los que destacan:

Método Explicación
match() busca el patrón al principio de la cadena
search() busca el patrón en cualquier parte de la cadena
findall() devuelve lista con las subcadena que encuentre
finditer() devuelve iterador con las subcadena que encuentre

Metacaracteres:

*. ^ $ + ? { } [ ] \ | ( )

Tienen un siginificado especial

[ ]

Especifica un conjunto de caracteres, en una lista o un rango (usando '-'). Los metacaracteres no tienen significado especial dentro.
Por ejemplo:
-[A-Z] caracter comprendido entre la A y Z en mayúsculas.
-[abc] cualquiera de éstos: a,b o c

patron = "t[a-z]la" 
cadena = "tila tela tla"
re_object = re.compile(patron)
print(re_object.findall(cadena))
['tila', 'tela']

^

Complementario. Por ejemplo: ^t cualquiera salvo 't'

patron = "[^321t]" 
cadena = "lote1234 @"
re_object = re.compile(patron)
print(re_object.findall(cadena))
['l', 'o', 'e', '4', ' ', '@']

|

Opcional, a elegir entre varios

patron = "pe[rro|na|lea]" 
cadena = "perro"
re_object = re.compile(patron)
print(re_object.search(cadena))
<re.Match object; span=(0, 3), match='per'>

\

Sirve para indicar formas especiales o para permitir el uso de caracteres especiales sin invocar su significado especial.

print ("Un salto de línea: \n...continuación\n")
print ("Anulamos el significado especial con otro '\\': \\n")
Un salto de línea: 
...continuación

Anulamos el significado especial con otro '\': \n
Metacaracter Explicación Equivalencia
\d cualquier dígito decimal [0-9]
\D cualquier caracter no dígito decimal [^0-9]
\w cualquier caracter alfanumérico [a-zA-Z0-9_]
\W cualquier caracter NO alfanumérico [^a-zA-Z0-9_]
\s cualquier caracter espacio en blanco [ \t\n\r\f\v]
\S cualquier caracter NO espacio en blanco [^ \t\n\r\f\v]

.

Cualquier carácter, salvo salto de línea. Alternativa: re.DOTALL (incluye salto de línea).

Ejemplos:

cadena = "lote1234 @"

re.findall(r'\d', cadena)
['1', '2', '3', '4']
re.findall(r'\D', cadena)
['l', 'o', 't', 'e', ' ', '@']
re.findall(r'\w', cadena)
['l', 'o', 't', 'e', '1', '2', '3', '4']
re.findall(r'\W', cadena)
[' ', '@']
re.findall(r'\s', cadena)
[' ']

( )

Extrae grupos de caracteres

cadena = "archivo123.pdf"
re.findall(r'(archivo\d*).pdf', cadena)
['archivo123']

Delimitadores:

Metacaracter Explicación
^ \$ inicio y fin de línea
\A \Z inicio y fin de texto
\b inicio o fin de una palabra
\B inicio o fin distinto de una palabra

Repeticiones:

Metacaracter Explicación
* 0 o más veces
+ 1 o más veces
? 0 o 1 vez
{m,n} de m a n veces


Ejemplos:

cadena = "csa casa caasa caaasa"

re.findall(r'ca*sa', cadena)
['csa', 'casa', 'caasa', 'caaasa']
re.findall(r'ca+sa', cadena)
['casa', 'caasa', 'caaasa']
re.findall(r'ca?sa', cadena)
['csa', 'casa']
re.findall(r'ca{2,3}sa', cadena)
['caasa', 'caaasa']

Ejemplos útiles

Correo electrónico

cadena = "usuario@empresa.es"
re.findall(r'\b[\w._%+-]+@[\w.-]+\.[a-zA-Z]{2,4}\b', cadena)
['usuario@empresa.es']

Seleccionar archivos de un tipo

cadena = "foto123.jpg foto32.png texto.doc imagen.gif"
re.findall(r'([\w]+\.[jpg|jpeg|png|gif])', cadena)
['foto123.j', 'foto32.p', 'imagen.g']