Lecciones del módulo (4/4)
Módulo re: regex en Python
El módulo re expone las expresiones regulares en Python. Si ya realizaste el curso de Regex en este sitio, toda la sintaxis te resultará familiar; aquí nos centraremos en las API.
Raw string: r"..."
Las expresiones regulares usan muchas barras invertidas (\d, \b, \s). Escríbelas siempre como raw strings para no tener que duplicarlas:
import re
# raw: \d is a single token
pattern = r"\d+"
# NOT raw: you would have to write "\\d+" otherwise Python interprets \d as "d"re.search: encontrar la primera ocurrencia
import re
m = re.search(r"\d+", "ho 42 mele e 17 pere")
m.group() # '42'
m.start() # 3
m.end() # 5Devuelve un objeto Match si lo encuentra, None en caso contrario. Patrón idiomático:
if m := re.search(r"\d+", testo):
print(m.group())re.match: solo al inicio de la cadena
re.match(r"\d+", "42 anni") # match!
re.match(r"\d+", "ho 42 anni") # None (doesn't start with a digit)Para buscar en cualquier parte, prefiere re.search.
re.findall: todas las ocurrencias
re.findall(r"\d+", "ho 42 mele, 17 pere, 3 banane")
# ['42', '17', '3']Si el patrón tiene grupos de captura, findall devuelve los grupos, no el emparejamiento completo:
re.findall(r"(\w+)@(\w+)", "ada@x bob@y")
# [('ada', 'x'), ('bob', 'y')]re.sub: sustitución
re.sub(r"\d+", "###", "ho 42 mele e 17 pere")
# 'ho ### mele e ### pere'También funciona con una función de reemplazo (que recibe el Match):
re.sub(r"\d+", lambda m: str(int(m.group()) * 2), "ho 42 mele")
# 'ho 84 mele'Grupos con nombre (named groups)
m = re.search(r"(?P<anno>\d{4})-(?P<mese>\d{2})-(?P<giorno>\d{2})", "2025-01-15")
m.group("anno") # '2025'
m.groupdict() # {'anno': '2025', 'mese': '01', 'giorno': '15'}Flags útiles
re.search(r"ciao", "CIAO", re.IGNORECASE) # case-insensitive
re.findall(r"^.+$", testo, re.MULTILINE) # ^/$ match every line
re.search(r"a.b", "a\nb", re.DOTALL) # . matches newline toore.finditer para seguridad de memoria
Si necesitas procesar emparejamientos en un bloque de texto enorme, re.findall asigna una lista en memoria que contiene todas las cadenas de texto extraídas. Se prefiere usar re.finditer(), que produce un iterador perezoso (lazy) de objetos Match, consumiendo el mínimo de memoria.
Pruébalo
Dado `text = 'ordine #123, totale €45.50, ricevuta #456'`, extrae TODOS los números de pedido (los dígitos después de #) en `orders` como una lista de cadenas. Evalúa `orders`.
Mostrar pista
re.findall(r"#(\d+)", text) — grupo de captura solo para dígitos.
Solución disponible después de 3 intentos
Ejercicio de repaso
Dado `s = 'tel: 06-12345678 e tel: 02-9876'`, reemplaza todos los números de teléfono (formato \d+-\d+) con la cadena 'XXX' y asígnalos a `masked`. Evalúa `masked`.
Mostrar pista
re.sub(r"\d+-\d+", "XXX", s)
Solución disponible después de 3 intentos
Desafío adicional
Importa el módulo `re`. Extrae todos los números compuestos de uno o más dígitos de la cadena `log_line = "Error 404 in 15ms"`. Guarda la lista en `numbers` y evalúala.
Mostrar pista
Usa re.findall(r'\d+', log_line) para extraer todos los números como una lista de cadenas.
Solución disponible después de 3 intentos