Las expresiones regulares proporcionan una manera eficiente de buscar y manipular cadenas de texto en Python. En lugar de depender de condicionales rígidos, permiten definir patrones flexibles para identificar secuencias específicas, como números de teléfono o direcciones de correo electrónico. El módulo estándar re facilita este trabajo, ya que no requiere instalación adicional.
Funciones Principales del Módulo re
re.findall(pattern, string, flags=0)
Esta función busca todas las coincidencias del patrón en la cadena y devuelve una lista con los resultados. Es útil para extraer múltiples elementos, como todos los dígitos o palabras clave.
import re
texto_busqueda = "aprendiendo_python_con_python_avanzado"
resultados = re.findall("python", texto_busqueda)
print(resultados) # Salida: ['python', 'python']
# Si no hay coincidencias, devuelve una lista vacía
sin_coincidencias = re.findall("java", texto_busqueda)
print(sin_coincidencias) # Salida: []
re.match(pattern, string, flags=0)
Comienza a buscar desde el inicio de la cadena y devuelve un objeto de coincidencia si encuentra una correspondencia, o None si no. Solo considera el principio de la cadena, ignorando coincidencias posteriores.
cadena_texto = "inicio_python_fin"
coincidencia = re.match("inicio", cadena_texto)
print(coincidencia) # Devuelve un objeto Match
if coincidencia:
print(coincidencia.span()) # Rango de índices (0, 6)
print(coincidencia.group()) # Texto coincidente: 'inicio'
# Ejemplo donde falla porque el patrón no está al inicio
cadena_ajena = "medio_python"
fallo = re.match("python", cadena_ajena)
print(fallo) # Salida: None
re.search(pattern, string, flags=0)
Busca la primera coincidencia del patrón en cualquier posición de la cadena, devolviendo un objeto de coincidencia o None. A diferencia de re.match, no se limita al inicio.
ejemplo_texto = "datos_python_intermedios_python"
encontrado = re.search("python", ejemplo_texto)
print(encontrado.group()) # Salida: 'python'
otro_texto = "preludio_python"
resultado = re.search("python", otro_texto)
if resultado:
print(resultado.group()) # Salida: 'python'
Metacaracteres y Cuantificadores
Los metacaracteres definen patrones específicos, mientras que los cuantificadores controlan la repetición. Se combinan para crear expresiones versátiles.
Metacaracteres Comunes
.- Coincide con cualquier carácter excepto el salto de línea.^- Indica el inicio de la cadena.$- Indica el final de la cadena.[]- Define un conjunto de caracteres permitidos, como[a-z]para letras minúsculas.[^]- Niega un conjunto, coincidiendo con caracteres fuera del especificado.()- Crea grupos para capturar subcadenas o aplicar alternancia.|- Actúa como operador "o" entre expresiones.\- Escapa caracteres especiales para tratarlos como literales.\d- Equivale a[0-9], coincidiendo con dígitos.\D- Coincide con no dígitos.\s- Representa caratceres de espacio en blanco.\S- Coincide con caracteres que no son espacios.\w- Incluye letras, dígitos y guiones bajos.
Ejemplos de Metacaracteres
ejemplo1 = "abcdefg"
print(re.findall(".", ejemplo1)) # Todos los caracteres individuales
ejemplo2 = "abc123def"
print(re.findall("^abc", ejemplo2)) # Coincide si empieza con 'abc'
ejemplo3 = "texto_final"
print(re.findall(r"final$", ejemplo3)) # Coincide si termina con 'final'
ejemplo4 = "mixto123abc"
print(re.findall(r"[a-d]", ejemplo4)) # Letras entre 'a' y 'd'
ejemplo5 = "numeros789"
print(re.findall(r"\d", ejemplo5)) # Dígitos: ['7', '8', '9']
ejemplo6 = "caden_a123"
print(re.findall(r"\w", ejemplo6)) # Caracteres alfanuméricos y guiones bajos
Cuantificadores
Controlan la frecuencia de aparición de un carácter o grupo. Modo por defecto es codicioso (greedy), buscando la coincidencia más larga; añadiendo ? se vuelve no codicioso, priorizando la más corta.
| Tipo | Sintaxis | Descripción | Ejemplo (patrón a) |
|---|---|---|---|
| Cero o más | * |
Repite 0 o más veces (codicioso) | a* coincide con "", "a", "aaa" |
| Cero o más | *? |
Repite 0 o más veces (no codicioso) | a*? prioriza "" |
| Una o más | + |
Repite 1 o más veces (codicioso) | a+ coincide con "a", "aaa" |
| Una o más | +? |
Repite 1 o más veces (no codicioso) | a+? prioriza "a" |
| Cero o una | ? |
Repite 0 o 1 vez (codicioso) | a? coincide con "", "a" |
| Veces exactas | {n} |
Exactamente n repeticiones | a{3} coincide con "aaa" |
| Rango | {m,n} |
Entre m y n veces (codicioso) | a{2,4} coincide con "aa" a "aaaa" |
Ejemplos de Cuantificadores
cadena_a = "anfaagfa"
print(re.findall(r"a*", cadena_a)) # Codicioso: ['a', '', '', 'aa', '', '', 'a', '']
print(re.findall(r"a*?", cadena_a)) # No codicioso: ['', 'a', '', '', '', 'a', '', 'a', '', '', '', 'a', '']
cadena_b = "aa123bb456"
print(re.findall(r"\d+", cadena_b)) # Dígitos repetidos: ['123', '456']
print(re.findall(r"\d+?", cadena_b)) # Un dígito a la vez: ['1', '2', '3', '4', '5', '6']
cadena_c = "abracadabra"
print(re.findall(r"a{2}", cadena_c)) # Dos 'a' seguidas: []
print(re.findall(r"a{1,3}", cadena_c)) # De 1 a 3 'a': ['a', 'a', 'a', 'a', 'a']
Grupos y Captura
Los paréntesis crean grupos, permitiendo extraer partes específicas de una coincidencia o aplicar lógica de alternancia.
Grupo de Captura
texto_grupo = "lenguaje_python_y_java"
print(re.findall(r"lenguaje_(python|java)", texto_grupo)) # Devuelve contenido del grupo: ['python', 'java']
Grupo No Captura
Usando ?: dentro del grupo, se evita capturar el subgrupo, devolviendo la coincidencia completa.
mismo_texto = "lenguaje_python_y_java"
print(re.findall(r"lenguaje_(?:python|java)", mismo_texto)) # Coincidencias completas: ['lenguaje_python', 'lenguaje_java']
Modo Codicioso vs. No Codicioso
Por defecto, los cuantificadores son codiciosos, buscando la coincidencia más larga posible. Al añadir ?, se cambia a modo no codicioso, priorizando la más corta.
cadena_codiciosa = "etiqueta_a12345_fin"
print(re.findall(r"a\d+", cadena_codiciosa)) # Codicioso: ['a12345']
print(re.findall(r"a\d?", cadena_codiciosa)) # No codicioso: ['a1']
cadena_otra = "abc123xyz"
print(re.findall(r".*", cadena_otra)) # Coincide con toda la cadena: ['abc123xyz', '']
Ejemplo Práctico: Validar Correo Electrónico
Para ilustrar un caso de uso, consiedremos la validación de una dirección de correo genérica con un patrón simple.
correo_entrada = input("Ingrese una dirección de correo: ")
patron_correo = r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$"
if re.findall(patron_correo, correo_entrada):
print("Correo válido.")
else:
print("Correo no válido.")
Resumen de Funciones
re.findall: Devuelve una lista con todas las coincidencias en la cadena.re.search: Devuelve un objeto de coincidencia para la primera aparición en cualquier posición.re.match: Devuelve un objeto de coincidencia solo si el patrón está al inicio, oNoneen caso contrario.