Python

Python

Tutorial Python: Módulo re

Aprende a usar el módulo re en Python para crear, buscar y manipular expresiones regulares con ejemplos prácticos y técnicas avanzadas.

Aprende Python y certifícate

Patrones básicos

Las expresiones regulares (o regex) son secuencias de caracteres que forman un patrón de búsqueda, principalmente utilizadas para operaciones de búsqueda y manipulación de texto. En Python, el módulo re proporciona todas las herramientas necesarias para trabajar con estas expresiones.

Un patrón básico es simplemente una secuencia de caracteres que se busca exactamente como está escrita. Por ejemplo, si buscamos el patrón "python" en un texto, encontraremos todas las ocurrencias exactas de esa palabra.

Caracteres literales

La forma más simple de una expresión regular es una secuencia de caracteres literales que coinciden exactamente con el texto buscado:

import re

texto = "Python es un lenguaje de programación versátil y potente."
resultado = re.search("Python", texto)

if resultado:
    print(f"Encontrado: {resultado.group()}")
    print(f"Posición: {resultado.start()}-{resultado.end()}")

En este ejemplo, buscamos la palabra "Python" en el texto. La función search() devuelve un objeto match si encuentra el patrón, o None si no lo encuentra. El método group() devuelve el texto coincidente, mientras que start() y end() indican las posiciones de inicio y fin.

Patrones de caracteres simples

Podemos buscar cualquier carácter de un conjunto utilizando corchetes []:

import re

texto = "El teléfono de Ana es 555-123-456 y el de Juan es 555-789-012"
patron = "[0-9]"  # Busca cualquier dígito

# Encontrar todas las coincidencias
coincidencias = re.findall(patron, texto)
print(coincidencias)  # Imprime todos los dígitos encontrados

Este patrón [0-9] coincide con cualquier dígito del 0 al 9. La función findall() devuelve una lista con todas las coincidencias encontradas.

Clases de caracteres predefinidas

El módulo re proporciona algunas clases de caracteres predefinidas que facilitan la creación de patrones comunes:

  • \d - Coincide con cualquier dígito (equivalente a [0-9])
  • \D - Coincide con cualquier carácter que no sea un dígito
  • \w - Coincide con cualquier carácter alfanumérico o guion bajo (equivalente a [a-zA-Z0-9_])
  • \W - Coincide con cualquier carácter que no sea alfanumérico
  • \s - Coincide con cualquier espacio en blanco (espacio, tabulación, salto de línea)
  • \S - Coincide con cualquier carácter que no sea un espacio en blanco
import re

texto = "Python 3.11 fue lanzado en 2022."

# Encontrar todos los dígitos
digitos = re.findall(r"\d", texto)
print("Dígitos:", digitos)

# Encontrar todas las palabras
palabras = re.findall(r"\w+", texto)  # El + indica "uno o más"
print("Palabras:", palabras)

Nota el uso de r antes de las cadenas de patrones. Esto crea una cadena raw (cruda) que evita que Python interprete las secuencias de escape como \d o \w.

Anclas y límites

Las anclas son caracteres especiales que indican posiciones específicas en el texto:

  • ^ - Coincide con el inicio de una línea
  • $ - Coincide con el final de una línea
  • \b - Coincide con un límite de palabra
  • \B - Coincide con cualquier posición que no sea un límite de palabra
import re

texto = "Python es genial. python es fácil de aprender."

# Buscar 'Python' solo al inicio de una línea
inicio_linea = re.findall(r"^Python", texto)
print("Al inicio:", inicio_linea)  # Encuentra 'Python'

# Buscar 'Python' sin importar mayúsculas/minúsculas
todas = re.findall(r"python", texto, re.IGNORECASE)
print("Todas:", todas)  # Encuentra ambas ocurrencias

# Buscar 'Python' como palabra completa
palabras_completas = re.findall(r"\bPython\b", texto, re.IGNORECASE)
print("Palabras completas:", palabras_completas)

El flag re.IGNORECASE (o re.I) hace que la búsqueda sea insensible a mayúsculas y minúsculas.

Patrones para validación básica

Las expresiones regulares son muy útiles para validar formatos comunes como correos electrónicos, números de teléfono o códigos postales:

import re

# Validar un correo electrónico simple
def validar_email(email):
    patron = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
    return bool(re.match(patron, email))

# Validar un número de teléfono español (9 dígitos)
def validar_telefono(telefono):
    patron = r"^\d{9}$"
    return bool(re.match(patron, telefono))

# Ejemplos
emails = ["usuario@dominio.com", "nombre.apellido@empresa.es", "invalido@.com"]
for email in emails:
    print(f"{email}: {'✓' if validar_email(email) else '✗'}")

telefonos = ["912345678", "600123456", "12345"]
for telefono in telefonos:
    print(f"{telefono}: {'✓' if validar_telefono(telefono) else '✗'}")

Extracción de información con patrones básicos

Podemos usar patrones para extraer información específica de textos:

import re

# Extraer fechas en formato DD/MM/AAAA
texto = "La reunión será el 15/06/2023 y la entrega está prevista para el 30/09/2023."
patron_fecha = r"\d{2}/\d{2}/\d{4}"
fechas = re.findall(patron_fecha, texto)
print("Fechas encontradas:", fechas)

# Extraer códigos de producto (formato: ABC-12345)
inventario = "Productos disponibles: ABC-12345, XYZ-98765, DEF-54321"
patron_producto = r"[A-Z]{3}-\d{5}"
productos = re.findall(patron_producto, inventario)
print("Códigos de producto:", productos)

Búsqueda y reemplazo básico

La función sub() permite reemplazar texto que coincide con un patrón:

import re

# Censurar números de teléfono
texto = "Contacta con Juan en el 912345678 o con Ana en el 600123456"
texto_censurado = re.sub(r"\d{9}", "XXX-XXX-XXX", texto)
print(texto_censurado)

# Formatear números de teléfono
def formatear_telefono(match):
    num = match.group(0)  # El texto completo que coincidió
    return f"{num[:3]}-{num[3:6]}-{num[6:]}"

texto_formateado = re.sub(r"\d{9}", formatear_telefono, texto)
print(texto_formateado)

Uso de patrones en análisis de logs

Las expresiones regulares son muy útiles para analizar archivos de registro:

import re

log = """
2023-06-15 08:30:45 INFO: Aplicación iniciada
2023-06-15 08:31:23 WARNING: Conexión lenta detectada
2023-06-15 08:32:10 ERROR: No se pudo conectar a la base de datos
2023-06-15 08:35:42 INFO: Conexión restablecida
"""

# Extraer todas las entradas de error
errores = re.findall(r".*ERROR.*", log)
print("Errores encontrados:")
for error in errores:
    print(f"  - {error.strip()}")

# Extraer fecha, hora y tipo de mensaje
patron_log = r"(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2}) (\w+): (.+)"
for linea in log.strip().split('\n'):
    match = re.match(patron_log, linea)
    if match:
        fecha, hora, tipo, mensaje = match.groups()
        if tipo == "WARNING" or tipo == "ERROR":
            print(f"Alerta [{tipo}] - {fecha} {hora}: {mensaje}")

Los patrones básicos de expresiones regulares son fundamentales para realizar operaciones de búsqueda y manipulación de texto en Python. Aunque pueden parecer complejos al principio, con práctica se convierten en una herramienta indispensable para el procesamiento de texto.

Metacaracteres y cuantificadores

Los metacaracteres y cuantificadores son elementos fundamentales que amplían considerablemente el poder de las expresiones regulares, permitiéndonos crear patrones más flexibles y precisos. Mientras que los patrones básicos nos permiten buscar coincidencias exactas, estos componentes avanzados nos dan la capacidad de definir patrones con variaciones y repeticiones.

Metacaracteres principales

Los metacaracteres son caracteres con significados especiales dentro de una expresión regular:

  • . - Coincide con cualquier carácter excepto saltos de línea
  • ^ - Coincide con el inicio de una cadena o línea
  • $ - Coincide con el final de una cadena o línea
  • | - Funciona como operador OR lógico entre patrones
  • () - Agrupa expresiones y captura coincidencias
  • [] - Define un conjunto de caracteres
  • \ - Escapa metacaracteres o introduce secuencias especiales

Veamos ejemplos prácticos de cómo utilizar estos metacaracteres:

import re

texto = "El precio es 23.50 euros y el código es ABC-123"

# El punto coincide con cualquier carácter
resultados = re.findall(r"c.d", texto)
print(f"Patrones 'c.d': {resultados}")  # Encuentra 'cód'

# Alternancia con el operador |
colores = "rojo verde azul amarillo"
resultados = re.findall(r"rojo|azul", colores)
print(f"Colores (rojo o azul): {resultados}")  # Encuentra 'rojo' y 'azul'

# Escapar metacaracteres para buscarlos literalmente
texto_puntos = "¿Cómo funciona esto...? No lo sé."
resultados = re.findall(r"\.\.\.", texto_puntos)
print(f"Puntos suspensivos: {resultados}")  # Encuentra '...'

Cuantificadores

Los cuantificadores especifican cuántas veces debe aparecer un elemento en el patrón:

  • * - Cero o más repeticiones (0+)
  • + - Una o más repeticiones (1+)
  • ? - Cero o una repetición (opcional)
  • {n} - Exactamente n repeticiones
  • {n,} - Al menos n repeticiones
  • {n,m} - Entre n y m repeticiones (inclusive)

Estos cuantificadores se aplican al elemento inmediatamente anterior, que puede ser un carácter, un grupo o una clase de caracteres:

import re

texto = "Teléfonos: 912345678, 91-234-56-78, 912-34-56-78 y 91 234 56 78"

# Buscar números de teléfono con diferentes formatos
patron = r"\d{2}[\s-]?\d{3}[\s-]?\d{2}[\s-]?\d{2}"
telefonos = re.findall(patron, texto)
print(f"Teléfonos encontrados: {telefonos}")

# Buscar palabras que empiecen con 'p' y tengan al menos 5 letras
texto = "Python es un programa potente para programación"
palabras_p = re.findall(r"\bp\w{4,}\b", texto, re.IGNORECASE)
print(f"Palabras con 'p' de 5+ letras: {palabras_p}")  # Encuentra 'Python', 'potente', 'programación'

Comportamiento voraz vs. no voraz

Por defecto, los cuantificadores son voraces (greedy), lo que significa que intentan coincidir con la mayor cantidad posible de caracteres. Podemos hacerlos no voraces (non-greedy o lazy) añadiendo un ? después del cuantificador:

import re

html = "<div>Primer contenido</div><div>Segundo contenido</div>"

# Cuantificador voraz (comportamiento predeterminado)
patron_voraz = r"<div>.*</div>"
resultado_voraz = re.findall(patron_voraz, html)
print(f"Coincidencia voraz: {resultado_voraz}")  # Captura todo desde el primer <div> hasta el último </div>

# Cuantificador no voraz
patron_no_voraz = r"<div>.*?</div>"
resultado_no_voraz = re.findall(patron_no_voraz, html)
print(f"Coincidencias no voraces: {resultado_no_voraz}")  # Captura cada <div> por separado

Combinación de metacaracteres y cuantificadores

La verdadera potencia de las expresiones regulares surge al combinar metacaracteres y cuantificadores:

import re

# Validar una dirección IPv4
def validar_ipv4(ip):
    # Patrón para un octeto: número entre 0 y 255
    octeto = r"(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)"
    patron = f"^{octeto}\.{octeto}\.{octeto}\.{octeto}$"
    return bool(re.match(patron, ip))

# Probar algunas direcciones IP
ips = ["192.168.1.1", "10.0.0.1", "256.0.0.1", "192.168.1", "a.b.c.d"]
for ip in ips:
    print(f"{ip}: {'✓' if validar_ipv4(ip) else '✗'}")

En este ejemplo, construimos un patrón complejo para validar direcciones IPv4. Cada octeto debe ser un número entre 0 y 255, lo que requiere combinar alternancia (|), agrupación (()) y cuantificadores específicos.

Patrones para análisis de texto

Los metacaracteres y cuantificadores son especialmente útiles para analizar textos estructurados:

import re

# Analizar un archivo de configuración simple
config = """
# Configuración del servidor
puerto = 8080
host = 192.168.1.10
timeout = 30s
max_conexiones = 100
"""

# Extraer pares clave-valor
patron = r"^(\w+)\s*=\s*(.+)$"
for linea in config.splitlines():
    match = re.match(patron, linea)
    if match:
        clave, valor = match.groups()
        print(f"Configuración: {clave} = {valor}")

# Extraer valores numéricos con unidades opcionales
patron_valor = r"(\d+)(\w*)"
for linea in config.splitlines():
    if "=" in linea:
        valor = linea.split("=")[1].strip()
        match = re.match(patron_valor, valor)
        if match:
            numero, unidad = match.groups()
            print(f"Valor numérico: {numero} {unidad if unidad else '(sin unidad)'}")

Validación de formatos comunes

Los metacaracteres y cuantificadores son esenciales para validar formatos comunes como URLs, correos electrónicos o fechas:

import re

# Validar URL
def validar_url(url):
    patron = r"^https?://(?:www\.)?[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)+(/[a-zA-Z0-9-._~:/?#[\]@!$&'()*+,;=]*)?$"
    return bool(re.match(patron, url))

# Validar fecha en formato DD/MM/AAAA
def validar_fecha(fecha):
    patron = r"^(0[1-9]|[12][0-9]|3[01])/(0[1-9]|1[0-2])/\d{4}$"
    if not re.match(patron, fecha):
        return False
    
    # Verificación adicional para fechas válidas
    dia, mes, año = map(int, fecha.split('/'))
    if mes in [4, 6, 9, 11] and dia > 30:
        return False
    if mes == 2:
        es_bisiesto = (año % 4 == 0 and año % 100 != 0) or (año % 400 == 0)
        if (es_bisiesto and dia > 29) or (not es_bisiesto and dia > 28):
            return False
    return True

# Ejemplos
urls = ["https://www.ejemplo.com", "http://ejemplo.com/ruta", "ftp://ejemplo.com"]
for url in urls:
    print(f"{url}: {'✓' if validar_url(url) else '✗'}")

fechas = ["31/01/2023", "29/02/2024", "29/02/2023", "31/04/2023"]
for fecha in fechas:
    print(f"{fecha}: {'✓' if validar_fecha(fecha) else '✗'}")

Extracción de información estructurada

Podemos usar metacaracteres y cuantificadores para extraer información estructurada de textos:

import re

# Extraer información de un log de servidor web
log_line = '192.168.1.10 - - [25/May/2023:10:15:32 +0200] "GET /index.html HTTP/1.1" 200 1234'

patron_log = r'(\d+\.\d+\.\d+\.\d+) .+ \[(.+?)\] "(\w+) (.+?) HTTP/[\d.]+?" (\d+) (\d+)'
match = re.match(patron_log, log_line)

if match:
    ip, fecha, metodo, ruta, codigo, tamaño = match.groups()
    print(f"IP: {ip}")
    print(f"Fecha: {fecha}")
    print(f"Método: {metodo}")
    print(f"Ruta: {ruta}")
    print(f"Código de respuesta: {codigo}")
    print(f"Tamaño: {tamaño} bytes")

Uso de flags con metacaracteres

Python permite modificar el comportamiento de las expresiones regulares mediante flags:

import re

texto = """Este es un texto
con múltiples líneas.
Python es genial.
python es fácil de aprender."""

# Sin el flag MULTILINE, ^ y $ coinciden con inicio y fin del texto completo
print("Sin MULTILINE:")
print(re.findall(r"^Python", texto))  # Solo encuentra 'Python' al inicio del texto

# Con MULTILINE, ^ y $ coinciden con inicio y fin de cada línea
print("\nCon MULTILINE:")
print(re.findall(r"^Python", texto, re.MULTILINE))  # Encuentra 'Python' al inicio de líneas

# Combinar flags
print("\nCon MULTILINE e IGNORECASE:")
print(re.findall(r"^python", texto, re.MULTILINE | re.IGNORECASE))  # Encuentra ambos 'Python'/'python'

# Flag DOTALL hace que '.' coincida también con saltos de línea
print("\nCon DOTALL:")
print(re.findall(r"es.*fácil", texto))  # No encuentra nada (hay saltos de línea entre 'es' y 'fácil')
print(re.findall(r"es.*fácil", texto, re.DOTALL))  # Encuentra desde 'es' hasta 'fácil' atravesando líneas

Los metacaracteres y cuantificadores transforman las expresiones regulares de simples herramientas de búsqueda a potentes instrumentos de análisis y validación de texto. Aunque requieren práctica para dominarlos, su flexibilidad los hace indispensables para cualquier tarea avanzada de procesamiento de texto en Python.

Grupos de captura

Los grupos de captura son una de las características más potentes de las expresiones regulares, ya que permiten extraer partes específicas del texto que coinciden con subpatrones dentro del patrón principal. En Python, estos grupos se crean mediante paréntesis () y nos permiten aislar y manipular fragmentos concretos de las coincidencias encontradas.

Fundamentos de los grupos de captura

Cuando encerramos una parte de una expresión regular entre paréntesis, creamos un grupo que no solo agrupa esos elementos sino que también "captura" el texto coincidente para su uso posterior:

import re

texto = "La fecha de hoy es 15/06/2023"
patron = r"(\d{2})/(\d{2})/(\d{4})"

resultado = re.search(patron, texto)
if resultado:
    fecha_completa = resultado.group(0)  # Toda la coincidencia
    dia = resultado.group(1)             # Primer grupo: día
    mes = resultado.group(2)             # Segundo grupo: mes
    año = resultado.group(3)             # Tercer grupo: año
    
    print(f"Fecha completa: {fecha_completa}")
    print(f"Día: {dia}, Mes: {mes}, Año: {año}")

En este ejemplo, cada componente de la fecha (día, mes y año) se captura en un grupo separado, lo que nos permite acceder a ellos individualmente mediante el método group().

Acceso a múltiples grupos

Cuando trabajamos con varios grupos de captura, podemos acceder a todos ellos de diferentes maneras:

import re

texto = "Contacto: Juan Pérez (juan.perez@ejemplo.com)"
patron = r"([A-Za-z\s]+) \(([^)]+)\)"

resultado = re.search(patron, texto)
if resultado:
    # Acceder a grupos individuales
    nombre = resultado.group(1)
    email = resultado.group(2)
    print(f"Nombre: {nombre}")
    print(f"Email: {email}")
    
    # Obtener todos los grupos como una tupla
    todos_los_grupos = resultado.groups()
    print(f"Todos los grupos: {todos_los_grupos}")
    
    # Desempaquetar directamente
    nombre_alt, email_alt = resultado.groups()
    print(f"Nombre (desempaquetado): {nombre_alt}")
    print(f"Email (desempaquetado): {email_alt}")

El método groups() devuelve una tupla con todos los grupos capturados, lo que facilita su desempaquetado en variables individuales.

Grupos nombrados

Para mejorar la legibilidad y mantenimiento del código, podemos asignar nombres a los grupos de captura utilizando la sintaxis (?P<nombre>patrón):

import re

log_entrada = "2023-06-15 14:32:15 - ERROR - Fallo en el módulo de autenticación"

# Usando grupos nombrados
patron = r"(?P<fecha>\d{4}-\d{2}-\d{2}) (?P<hora>\d{2}:\d{2}:\d{2}) - (?P<nivel>\w+) - (?P<mensaje>.*)"

resultado = re.search(patron, log_entrada)
if resultado:
    # Acceder por nombre
    fecha = resultado.group("fecha")
    hora = resultado.group("hora")
    nivel = resultado.group("nivel")
    mensaje = resultado.group("mensaje")
    
    print(f"Fecha: {fecha}")
    print(f"Hora: {hora}")
    print(f"Nivel: {nivel}")
    print(f"Mensaje: {mensaje}")
    
    # También podemos obtener un diccionario con todos los grupos nombrados
    datos = resultado.groupdict()
    print(f"Diccionario de grupos: {datos}")

Los grupos nombrados hacen que el código sea más legible y mantenible, especialmente cuando trabajamos con patrones complejos que contienen muchos grupos.

Grupos no capturantes

En ocasiones, necesitamos agrupar elementos de un patrón sin capturar su contenido. Para esto usamos la sintaxis (?:patrón):

import re

texto = "El precio es 23.50 euros"

# Grupo capturante normal
patron_capturante = r"(\d+\.\d+) euros"
resultado = re.search(patron_capturante, texto)
print(f"Grupos capturados: {resultado.groups()}")  # ('23.50',)

# Grupo no capturante
patron_no_capturante = r"(?:\d+\.\d+) euros"
resultado = re.search(patron_no_capturante, texto)
print(f"Grupos capturados: {resultado.groups()}")  # ()

# Combinando grupos capturantes y no capturantes
patron_mixto = r"(\d+)(?:\.)(\d+) euros"
resultado = re.search(patron_mixto, texto)
print(f"Grupos capturados: {resultado.groups()}")  # ('23', '50')

Los grupos no capturantes son útiles cuando necesitamos la funcionalidad de agrupación (como aplicar un cuantificador a varios elementos) pero no necesitamos extraer ese contenido específico.

Referencias hacia atrás (backreferences)

Una característica poderosa de los grupos de captura es la capacidad de hacer referencia a ellos dentro de la misma expresión regular mediante backreferences. Esto se hace con \número o \g<nombre> para grupos nombrados:

import re

# Encontrar palabras repetidas
texto = "Este es es un ejemplo de texto con palabras palabras repetidas."

# Usando referencia numérica
patron = r"\b(\w+)\s+\1\b"
palabras_repetidas = re.findall(patron, texto)
print(f"Palabras repetidas: {palabras_repetidas}")  # ['es', 'palabras']

# Encontrar etiquetas HTML coincidentes
html = "<div><p>Contenido del párrafo</p></div><span>Otro texto</span>"

# Usando referencia numérica para asegurar que las etiquetas coincidan
patron_html = r"<(\w+)>.*?</\1>"
etiquetas = re.findall(patron_html, html)
print(f"Etiquetas encontradas: {etiquetas}")  # ['p', 'span']

# Con grupos nombrados
patron_html_nombrado = r"<(?P<tag>\w+)>.*?</(?P=tag)>"
etiquetas = re.findall(patron_html_nombrado, html)
print(f"Etiquetas encontradas (grupos nombrados): {etiquetas}")  # ['p', 'span']

Las referencias hacia atrás son extremadamente útiles para encontrar patrones que deben coincidir consigo mismos, como etiquetas HTML, comillas coincidentes o palabras repetidas.

Grupos en sustituciones

Los grupos de captura son especialmente útiles en operaciones de sustitución, donde podemos reorganizar o transformar el texto capturado:

import re

# Invertir el orden de nombre y apellido
nombres = ["García, Ana", "López, Carlos", "Martínez, Elena"]

for nombre in nombres:
    # Capturamos apellido y nombre, y los reorganizamos en la sustitución
    nombre_formateado = re.sub(r"(\w+), (\w+)", r"\2 \1", nombre)
    print(f"Original: {nombre} -> Formateado: {nombre_formateado}")

# Formatear números de teléfono
telefonos = ["912345678", "611234567", "942123456"]

for telefono in telefonos:
    # Dividimos el número en grupos y lo formateamos
    telefono_formateado = re.sub(r"(\d{3})(\d{3})(\d{3})", r"\1-\2-\3", telefono)
    print(f"Original: {telefono} -> Formateado: {telefono_formateado}")

En estos ejemplos, usamos \1, \2, etc., en la cadena de reemplazo para hacer referencia a los grupos capturados en el patrón original.

Grupos con funciones de sustitución

Podemos llevar las sustituciones un paso más allá combinando grupos de captura con funciones de reemplazo:

import re

# Convertir fechas de formato DD/MM/AAAA a AAAA-MM-DD
texto = "Fechas importantes: 15/06/2023, 22/07/2023 y 30/09/2023"

def convertir_formato_fecha(match):
    dia = match.group(1)
    mes = match.group(2)
    año = match.group(3)
    return f"{año}-{mes}-{dia}"

texto_convertido = re.sub(r"(\d{2})/(\d{2})/(\d{4})", convertir_formato_fecha, texto)
print(f"Texto convertido: {texto_convertido}")

# Convertir temperaturas de Celsius a Fahrenheit
texto_temp = "Temperaturas: 20°C en Madrid, 15°C en Barcelona, 25°C en Sevilla"

def celsius_a_fahrenheit(match):
    celsius = int(match.group(1))
    fahrenheit = celsius * 9/5 + 32
    return f"{fahrenheit:.1f}°F"

texto_convertido = re.sub(r"(\d+)°C", celsius_a_fahrenheit, texto_temp)
print(f"Temperaturas convertidas: {texto_convertido}")

Esta técnica es extremadamente poderosa para transformaciones complejas, ya que podemos aplicar cualquier lógica de programación a los valores capturados.

Extracción de datos estructurados

Los grupos de captura son ideales para extraer datos estructurados de textos como logs, informes o documentos:

import re

# Extraer información de un registro de ventas
registro = """
Producto: Laptop XPS 13
Precio: 1299.99€
Cantidad: 3
Cliente: María González
Fecha: 15/06/2023
"""

# Definimos patrones para cada campo con grupos nombrados
patrones = {
    "producto": r"Producto: (?P<valor>.*)",
    "precio": r"Precio: (?P<valor>\d+\.\d+)€",
    "cantidad": r"Cantidad: (?P<valor>\d+)",
    "cliente": r"Cliente: (?P<valor>.*)",
    "fecha": r"Fecha: (?P<valor>\d{2}/\d{2}/\d{4})"
}

# Extraemos cada campo
datos_venta = {}
for campo, patron in patrones.items():
    match = re.search(patron, registro)
    if match:
        datos_venta[campo] = match.group("valor")

print("Datos extraídos:")
for campo, valor in datos_venta.items():
    print(f"  {campo.capitalize()}: {valor}")

# Calculamos el total
if "precio" in datos_venta and "cantidad" in datos_venta:
    total = float(datos_venta["precio"]) * int(datos_venta["cantidad"])
    print(f"Total de la venta: {total:.2f}€")

Este enfoque permite extraer y procesar datos de manera estructurada a partir de textos que siguen un formato específico pero no están en un formato de datos como JSON o CSV.

Anidación de grupos

Los grupos de captura pueden anidarse para manejar estructuras jerárquicas:

import re

# Analizar una expresión matemática simple
expresion = "(2 + 3) * (4 - 1)"

# Capturamos la expresión completa y cada paréntesis por separado
patron = r"\(([^()]+)\) *([*+/-]) *\(([^()]+)\)"
match = re.search(patron, expresion)

if match:
    expr1 = match.group(1)  # "2 + 3"
    operador = match.group(2)  # "*"
    expr2 = match.group(3)  # "4 - 1"
    
    print(f"Primera expresión: {expr1}")
    print(f"Operador: {operador}")
    print(f"Segunda expresión: {expr2}")
    
    # Podemos analizar más profundamente cada subexpresión
    def evaluar_subexpresion(expr):
        patron_sub = r"(\d+) *([+\-*/]) *(\d+)"
        sub_match = re.search(patron_sub, expr)
        if sub_match:
            num1 = int(sub_match.group(1))
            op = sub_match.group(2)
            num2 = int(sub_match.group(3))
            
            if op == '+': return num1 + num2
            if op == '-': return num1 - num2
            if op == '*': return num1 * num2
            if op == '/': return num1 / num2
    
    resultado1 = evaluar_subexpresion(expr1)
    resultado2 = evaluar_subexpresion(expr2)
    
    print(f"Resultado de {expr1} = {resultado1}")
    print(f"Resultado de {expr2} = {resultado2}")
    
    # Evaluamos la expresión completa
    if operador == '+': resultado_final = resultado1 + resultado2
    if operador == '-': resultado_final = resultado1 - resultado2
    if operador == '*': resultado_final = resultado1 * resultado2
    if operador == '/': resultado_final = resultado1 / resultado2
    
    print(f"Resultado final: {expresion} = {resultado_final}")

La anidación de grupos permite descomponer problemas complejos en partes más manejables, facilitando el análisis de estructuras jerárquicas como expresiones matemáticas, código fuente o documentos estructurados.

Los grupos de captura son una herramienta fundamental para extraer y manipular información específica de textos mediante expresiones regulares. Dominando esta técnica, podemos realizar tareas avanzadas de procesamiento de texto con código conciso y eficiente.

Funciones de búsqueda y reemplazo

El módulo re de Python ofrece un conjunto completo de funciones para realizar operaciones de búsqueda y reemplazo en textos utilizando expresiones regulares. Estas funciones nos permiten localizar patrones específicos y manipular el texto de forma precisa y eficiente.

Principales funciones de búsqueda

El módulo re proporciona varias funciones para buscar patrones en textos, cada una con un propósito específico:

  • re.search(): Busca la primera coincidencia del patrón en cualquier parte del texto.
  • re.match(): Busca el patrón solo al inicio del texto.
  • re.fullmatch(): Verifica si todo el texto coincide exactamente con el patrón.
  • re.findall(): Encuentra todas las coincidencias no superpuestas y las devuelve como una lista.
  • re.finditer(): Similar a findall(), pero devuelve un iterador de objetos match.

Veamos ejemplos prácticos de cada una:

import re

texto = "Python es un lenguaje versátil. Python es fácil de aprender."

# re.search() - encuentra la primera coincidencia
resultado = re.search(r"Python", texto)
print(f"search: {resultado.group() if resultado else 'No encontrado'}")  # Python

# re.match() - busca solo al inicio
resultado = re.match(r"Python", texto)
print(f"match: {resultado.group() if resultado else 'No encontrado'}")  # Python

# re.match() en otra posición
resultado = re.match(r"es", texto)
print(f"match 'es': {resultado.group() if resultado else 'No encontrado'}")  # No encontrado

# re.fullmatch() - todo el texto debe coincidir
resultado = re.fullmatch(r"Python.*aprender\.", texto)
print(f"fullmatch: {resultado.group() if resultado else 'No encontrado'}")  # Coincide con todo el texto

# re.findall() - encuentra todas las coincidencias
coincidencias = re.findall(r"Python", texto)
print(f"findall: {coincidencias}")  # ['Python', 'Python']

# re.finditer() - iterador de coincidencias
for match in re.finditer(r"Python", texto):
    print(f"finditer: '{match.group()}' en posición {match.start()}-{match.end()}")

Objetos Match y sus métodos

Cuando una búsqueda tiene éxito, las funciones como search(), match() y fullmatch() devuelven un objeto Match que contiene información sobre la coincidencia encontrada:

import re

texto = "Contacto: support@ejemplo.com (Soporte Técnico)"
resultado = re.search(r"(\w+)@(\w+)\.(\w+)", texto)

if resultado:
    # Métodos básicos del objeto Match
    print(f"Texto completo coincidente: {resultado.group()}")  # support@ejemplo.com
    print(f"Posición inicial: {resultado.start()}")  # 10
    print(f"Posición final: {resultado.end()}")  # 27
    print(f"Tupla (inicio, fin): {resultado.span()}")  # (10, 27)
    
    # Acceso a grupos específicos
    print(f"Usuario: {resultado.group(1)}")  # support
    print(f"Dominio: {resultado.group(2)}")  # ejemplo
    print(f"TLD: {resultado.group(3)}")  # com
    
    # Posiciones de grupos específicos
    print(f"Posición del usuario: {resultado.start(1)}-{resultado.end(1)}")  # 10-17

Funciones de reemplazo

El módulo re ofrece potentes funciones para reemplazar texto basado en patrones:

  • re.sub(): Reemplaza todas las coincidencias del patrón.
  • re.subn(): Similar a sub(), pero también devuelve el número de sustituciones realizadas.
import re

texto = "El teléfono de Juan es 912345678 y el de Ana es 611234567"

# Reemplazo básico
resultado = re.sub(r"\d{9}", "XXX-XXX-XXX", texto)
print(f"Teléfonos censurados: {resultado}")

# Reemplazo con límite de ocurrencias (count)
resultado = re.sub(r"\d{9}", "XXX-XXX-XXX", texto, count=1)
print(f"Solo primer teléfono censurado: {resultado}")

# re.subn() - devuelve el texto modificado y el número de sustituciones
resultado, num_reemplazos = re.subn(r"\d{9}", "XXX-XXX-XXX", texto)
print(f"Texto modificado: {resultado}")
print(f"Número de reemplazos: {num_reemplazos}")  # 2

Reemplazo con funciones

Una característica poderosa de re.sub() es la capacidad de usar una función para determinar el texto de reemplazo. La función recibe un objeto match y debe devolver la cadena de reemplazo:

import re

# Formatear números de teléfono
def formatear_telefono(match):
    numero = match.group(0)  # El texto completo que coincidió
    return f"{numero[:3]}-{numero[3:6]}-{numero[6:]}"

texto = "Contactos: 912345678, 611234567"
resultado = re.sub(r"\d{9}", formatear_telefono, texto)
print(f"Teléfonos formateados: {resultado}")  # 912-345-678, 611-234-567

# Convertir temperaturas de Celsius a Fahrenheit
def celsius_a_fahrenheit(match):
    celsius = float(match.group(1))
    fahrenheit = celsius * 9/5 + 32
    return f"{fahrenheit:.1f}°F"

texto_clima = "Temperaturas: Madrid 25°C, Barcelona 22°C, Sevilla 30°C"
resultado = re.sub(r"(\d+(?:\.\d+)?)°C", celsius_a_fahrenheit, texto_clima)
print(f"Temperaturas convertidas: {resultado}")

Compilación de patrones

Para mejorar el rendimiento cuando usamos el mismo patrón repetidamente, podemos compilarlo previamente con re.compile():

import re
import time

# Patrón para validar correos electrónicos
patron_email = re.compile(r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}")

# Lista de textos para analizar
textos = [
    "Contacto: usuario@dominio.com",
    "Enviar información a: info@empresa.es",
    "Mi dirección es usuario@dominio",  # Inválido
    "Correo: soporte@servicio.tech"
]

# Usando el patrón compilado
for texto in textos:
    match = patron_email.search(texto)
    if match:
        print(f"Email válido encontrado: {match.group()}")
    else:
        print(f"No se encontró email válido en: '{texto}'")

# Medición de rendimiento
def test_sin_compilar():
    for _ in range(10000):
        re.search(r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}", "usuario@dominio.com")

def test_compilado():
    patron = re.compile(r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}")
    for _ in range(10000):
        patron.search("usuario@dominio.com")

# Comparación de tiempos
inicio = time.time()
test_sin_compilar()
tiempo_sin_compilar = time.time() - inicio

inicio = time.time()
test_compilado()
tiempo_compilado = time.time() - inicio

print(f"Tiempo sin compilar: {tiempo_sin_compilar:.4f} segundos")
print(f"Tiempo compilado: {tiempo_compilado:.4f} segundos")
print(f"Mejora de rendimiento: {(tiempo_sin_compilar/tiempo_compilado):.2f}x")

Un patrón compilado tiene los mismos métodos que el módulo re (search(), match(), sub(), etc.), pero ya no necesita el patrón como primer argumento.

Flags en búsqueda y reemplazo

Los flags modifican el comportamiento de las operaciones de búsqueda y reemplazo:

import re

texto = """Python es un lenguaje de programación.
python es fácil de aprender.
PYTHON tiene una sintaxis clara."""

# Búsqueda sin flags
resultados = re.findall(r"python", texto)
print(f"Sin flags: {resultados}")  # Solo encuentra 'python' en minúsculas

# Búsqueda insensible a mayúsculas/minúsculas
resultados = re.findall(r"python", texto, re.IGNORECASE)
print(f"Con IGNORECASE: {resultados}")  # Encuentra todas las variantes

# Múltiples flags combinados con el operador OR (|)
texto_multilinea = """Línea 1: python
Línea 2: PYTHON
Línea 3: Python"""

# re.MULTILINE hace que ^ y $ coincidan con inicio/fin de cada línea
# re.IGNORECASE hace la búsqueda insensible a mayúsculas/minúsculas
resultados = re.findall(r"^línea \d: python$", texto_multilinea, 
                        re.MULTILINE | re.IGNORECASE)
print(f"Con MULTILINE e IGNORECASE: {resultados}")

Los flags también se pueden incluir dentro del patrón usando la sintaxis (?flags):

import re

texto = """Python es un lenguaje.
python es fácil."""

# Flags dentro del patrón
resultados = re.findall(r"(?i)python", texto)  # Equivalente a re.IGNORECASE
print(f"Flag inline: {resultados}")  # ['Python', 'python']

# Flags comunes en forma inline:
# (?i) - IGNORECASE
# (?m) - MULTILINE
# (?s) - DOTALL
# (?x) - VERBOSE

Búsqueda y reemplazo en archivos

Un caso de uso común es procesar archivos de texto línea por línea:

import re

def procesar_archivo(archivo_entrada, archivo_salida, patron, reemplazo):
    """Procesa un archivo línea por línea aplicando un patrón de búsqueda y reemplazo."""
    contador = 0
    
    with open(archivo_entrada, 'r', encoding='utf-8') as entrada:
        with open(archivo_salida, 'w', encoding='utf-8') as salida:
            for linea in entrada:
                # Aplicar el reemplazo y contar las sustituciones
                nueva_linea, num_reemplazos = re.subn(patron, reemplazo, linea)
                contador += num_reemplazos
                salida.write(nueva_linea)
    
    return contador

# Ejemplo de uso (comentado para evitar errores si no existen los archivos)
"""
# Normalizar fechas de formato DD/MM/AAAA a AAAA-MM-DD
num_reemplazos = procesar_archivo(
    'datos.txt', 
    'datos_normalizados.txt',
    r'(\d{2})/(\d{2})/(\d{4})',
    r'\3-\2-\1'
)
print(f"Se normalizaron {num_reemplazos} fechas en el archivo")
"""

Extracción de datos estructurados

Podemos combinar las funciones de búsqueda con estructuras de datos para extraer información estructurada:

import re

# Texto de ejemplo: un log de servidor
log = """
2023-06-15 08:30:45 INFO [Server] Servidor iniciado en puerto 8080
2023-06-15 08:31:23 WARNING [Database] Conexión lenta detectada
2023-06-15 08:32:10 ERROR [Auth] Fallo de autenticación: usuario 'admin'
2023-06-15 08:35:42 INFO [Server] Cliente conectado: 192.168.1.10
"""

# Patrón para extraer componentes del log
patron = r"(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) (\w+) \[(\w+)\] (.+)"

# Extraer y estructurar los datos
entradas_log = []
for linea in log.strip().split('\n'):
    match = re.search(patron, linea)
    if match:
        timestamp, nivel, componente, mensaje = match.groups()
        entradas_log.append({
            'timestamp': timestamp,
            'nivel': nivel,
            'componente': componente,
            'mensaje': mensaje
        })

# Filtrar y procesar los datos extraídos
errores = [entrada for entrada in entradas_log if entrada['nivel'] == 'ERROR']
warnings = [entrada for entrada in entradas_log if entrada['nivel'] == 'WARNING']

print(f"Total de entradas: {len(entradas_log)}")
print(f"Errores: {len(errores)}")
print(f"Warnings: {len(warnings)}")

# Mostrar mensajes de error
print("\nMensajes de error:")
for error in errores:
    print(f"[{error['timestamp']}] {error['componente']}: {error['mensaje']}")

Validación de entrada con búsqueda y reemplazo

Podemos usar las funciones de búsqueda y reemplazo para validar y limpiar datos de entrada:

import re

def validar_y_formatear_telefono(telefono):
    """Valida y formatea un número de teléfono español."""
    # Eliminar todos los caracteres no numéricos
    solo_numeros = re.sub(r'\D', '', telefono)
    
    # Validar que sea un número español válido (9 dígitos)
    if not re.fullmatch(r'\d{9}', solo_numeros):
        return None
    
    # Formatear el número según el tipo (fijo o móvil)
    primer_digito = solo_numeros[0]
    if primer_digito in '67':  # Móvil
        return re.sub(r'(\d{3})(\d{3})(\d{3})', r'\1 \2 \3', solo_numeros)
    else:  # Fijo
        return re.sub(r'(\d{3})(\d{2})(\d{2})(\d{2})', r'\1 \2 \3 \4', solo_numeros)

# Probar con diferentes formatos de entrada
telefonos = [
    "912345678",
    "(91) 234-56-78",
    "600 12 34 56",
    "6-0-0-1-2-3-4-5-6",
    "91.234.56.78",
    "1234"  # Inválido
]

for telefono in telefonos:
    resultado = validar_y_formatear_telefono(telefono)
    if resultado:
        print(f"'{telefono}' → '{resultado}'")
    else:
        print(f"'{telefono}' → Formato inválido")

Búsqueda y reemplazo en análisis de texto

Las funciones de búsqueda y reemplazo son útiles para análisis de texto y procesamiento de lenguaje natural básico:

import re

def analizar_texto(texto):
    """Realiza un análisis básico de un texto."""
    # Convertir a minúsculas y eliminar puntuación
    texto_limpio = re.sub(r'[^\w\s]', '', texto.lower())
    
    # Contar palabras
    palabras = re.findall(r'\b\w+\b', texto_limpio)
    num_palabras = len(palabras)
    
    # Contar frecuencia de palabras
    frecuencia = {}
    for palabra in palabras:
        if len(palabra) > 3:  # Ignorar palabras muy cortas
            frecuencia[palabra] = frecuencia.get(palabra, 0) + 1
    
    # Palabras más comunes
    palabras_comunes = sorted(frecuencia.items(), key=lambda x: x[1], reverse=True)[:5]
    
    # Contar oraciones
    oraciones = re.findall(r'[^.!?]+[.!?]', texto)
    num_oraciones = len(oraciones)
    
    return {
        'num_palabras': num_palabras,
        'num_oraciones': num_oraciones,
        'palabras_comunes': palabras_comunes,
        'longitud_promedio_oracion': num_palabras / num_oraciones if num_oraciones else 0
    }

# Ejemplo
texto_muestra = """
Python es un lenguaje de programación interpretado cuya filosofía hace hincapié en la legibilidad de su código. 
Es un lenguaje multiparadigma, ya que soporta orientación a objetos, programación imperativa y programación funcional.
Python es administrado por la Python Software Foundation. Posee una licencia de código abierto.
"""

resultado = analizar_texto(texto_muestra)
print(f"Análisis de texto:")
print(f"- Palabras: {resultado['num_palabras']}")
print(f"- Oraciones: {resultado['num_oraciones']}")
print(f"- Longitud promedio de oración: {resultado['longitud_promedio_oracion']:.1f} palabras")
print(f"- Palabras más comunes:")
for palabra, frecuencia in resultado['palabras_comunes']:
    print(f"  * '{palabra}': {frecuencia} veces")

Rendimiento y consideraciones prácticas

Al trabajar con expresiones regulares, es importante considerar el rendimiento, especialmente con textos grandes:

import re
import time

# Generar un texto grande para la prueba
texto_grande = "Python es un lenguaje de programación. " * 10000

# Comparar rendimiento de diferentes enfoques
def test_findall():
    return re.findall(r"Python", texto_grande)

def test_finditer():
    return list(re.finditer(r"Python", texto_grande))

def test_compilado_findall():
    patron = re.compile(r"Python")
    return patron.findall(texto_grande)

# Medir tiempos
funciones = [test_findall, test_finditer, test_compilado_findall]
for func in funciones:
    inicio = time.time()
    resultado = func()
    tiempo = time.time() - inicio
    print(f"{func.__name__}: {len(resultado)} coincidencias en {tiempo:.4f} segundos")

# Consejos prácticos para expresiones regulares eficientes
print("\nConsejos para expresiones regulares eficientes:")
print("1. Compila patrones que uses repetidamente")
print("2. Usa finditer() en lugar de findall() cuando necesites información de posición")
print("3. Evita patrones con cuantificadores voraces (*, +) seguidos de muchas alternativas")
print("4. Usa grupos no capturantes (?:...) cuando no necesites el contenido")
print("5. Ancla tus patrones (^, $, \\b) cuando sea posible para limitar la búsqueda")

Aplicaciones prácticas avanzadas

Las funciones de búsqueda y reemplazo pueden aplicarse a problemas complejos del mundo real:

import re

# Ejemplo: Extraer y analizar datos de un log de servidor web
log_apache = """
192.168.1.10 - - [15/Jun/2023:10:12:01 +0200] "GET /index.html HTTP/1.1" 200 2048
10.0.0.5 - - [15/Jun/2023:10:12:05 +0200] "POST /login HTTP/1.1" 302 0
192.168.1.15 - - [15/Jun/2023:10:12:10 +0200] "GET /images/logo.png HTTP/1.1" 200 4096
10.0.0.8 - - [15/Jun/2023:10:12:15 +0200] "GET /admin HTTP/1.1" 403 1024
192.168.1.20 - - [15/Jun/2023:10:12:20 +0200] "GET /api/data HTTP/1.1" 500 1253
"""

# Patrón para analizar entradas de log de Apache
patron_log = re.compile(r"""
    (\d+\.\d+\.\d+\.\d+)         # Dirección IP
    \s+-\s+-\s+                  # Separadores
    \[([^\]]+)\]                 # Fecha y hora entre corchetes
    \s+"([A-Z]+)\s+              # Método HTTP
    ([^\s]+)\s+                  # Ruta solicitada
    HTTP/[\d.]+"\s+              # Versión HTTP
    (\d+)\s+                     # Código de estado
    (\d+)                        # Tamaño de respuesta
""", re.VERBOSE)

# Analizar el log
estadisticas = {
    'total_solicitudes': 0,
    'por_metodo': {},
    'por_codigo': {},
    'tamaño_total': 0
}

for linea in log_apache.strip().split('\n'):
    match = patron_log.search(linea)
    if match:
        ip, fecha, metodo, ruta, codigo, tamaño = match.groups()
        
        estadisticas['total_solicitudes'] += 1
        estadisticas['por_metodo'][metodo] = estadisticas['por_metodo'].get(metodo, 0) + 1
        estadisticas['por_codigo'][codigo] = estadisticas['por_codigo'].get(codigo, 0) + 1
        estadisticas['tamaño_total'] += int(tamaño)

# Mostrar resultados
print("Análisis de log de servidor web:")
print(f"Total de solicitudes: {estadisticas['total_solicitudes']}")
print("Por método HTTP:")
for metodo, count in estadisticas['por_metodo'].items():
    print(f"  - {metodo}: {count}")
print("Por código de estado:")
for codigo, count in estadisticas['por_codigo'].items():
    print(f"  - {codigo}: {count}")
print(f"Tamaño total transferido: {estadisticas['tamaño_total']/1024:.2f} KB")

Las funciones de búsqueda y reemplazo del módulo re son herramientas esenciales para el procesamiento de texto en Python. Dominando estas funciones, puedes realizar desde tareas simples de validación hasta complejos análisis de datos textuales con código conciso y eficiente.

Aprende Python online

Otras lecciones de Python

Accede a todas las lecciones de Python y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Introducción A Python

Python

Introducción

Instalación Y Creación De Proyecto

Python

Introducción

Tema 2: Tipos De Datos, Variables Y Operadores

Python

Introducción

Instalación De Python

Python

Introducción

Tipos De Datos

Python

Sintaxis

Variables

Python

Sintaxis

Operadores

Python

Sintaxis

Estructuras De Control

Python

Sintaxis

Funciones

Python

Sintaxis

Estructuras Control Iterativo

Python

Sintaxis

Estructuras Control Condicional

Python

Sintaxis

Testing Con Pytest

Python

Sintaxis

Listas

Python

Estructuras De Datos

Tuplas

Python

Estructuras De Datos

Diccionarios

Python

Estructuras De Datos

Conjuntos

Python

Estructuras De Datos

Comprehensions

Python

Estructuras De Datos

Clases Y Objetos

Python

Programación Orientada A Objetos

Excepciones

Python

Programación Orientada A Objetos

Encapsulación

Python

Programación Orientada A Objetos

Herencia

Python

Programación Orientada A Objetos

Polimorfismo

Python

Programación Orientada A Objetos

Mixins Y Herencia Múltiple

Python

Programación Orientada A Objetos

Métodos Especiales (Dunder Methods)

Python

Programación Orientada A Objetos

Composición De Clases

Python

Programación Orientada A Objetos

Funciones Lambda

Python

Programación Funcional

Aplicación Parcial

Python

Programación Funcional

Entrada Y Salida, Manejo De Archivos

Python

Programación Funcional

Decoradores

Python

Programación Funcional

Generadores

Python

Programación Funcional

Paradigma Funcional

Python

Programación Funcional

Composición De Funciones

Python

Programación Funcional

Funciones Orden Superior Map Y Filter

Python

Programación Funcional

Funciones Auxiliares

Python

Programación Funcional

Reducción Y Acumulación

Python

Programación Funcional

Archivos Comprimidos

Python

Entrada Y Salida Io

Entrada Y Salida Avanzada

Python

Entrada Y Salida Io

Archivos Temporales

Python

Entrada Y Salida Io

Contexto With

Python

Entrada Y Salida Io

Módulo Csv

Python

Biblioteca Estándar

Módulo Json

Python

Biblioteca Estándar

Módulo Datetime

Python

Biblioteca Estándar

Módulo Math

Python

Biblioteca Estándar

Módulo Os

Python

Biblioteca Estándar

Módulo Re

Python

Biblioteca Estándar

Módulo Random

Python

Biblioteca Estándar

Módulo Time

Python

Biblioteca Estándar

Módulo Collections

Python

Biblioteca Estándar

Módulo Sys

Python

Biblioteca Estándar

Módulo Statistics

Python

Biblioteca Estándar

Módulo Pickle

Python

Biblioteca Estándar

Módulo Pathlib

Python

Biblioteca Estándar

Importar Módulos Y Paquetes

Python

Paquetes Y Módulos

Crear Módulos Y Paquetes

Python

Paquetes Y Módulos

Entornos Virtuales (Virtualenv, Venv)

Python

Entorno Y Dependencias

Gestión De Dependencias (Pip, Requirements.txt)

Python

Entorno Y Dependencias

Python-dotenv Y Variables De Entorno

Python

Entorno Y Dependencias

Acceso A Datos Con Mysql, Pymongo Y Pandas

Python

Acceso A Bases De Datos

Acceso A Mongodb Con Pymongo

Python

Acceso A Bases De Datos

Acceso A Mysql Con Mysql Connector

Python

Acceso A Bases De Datos

Novedades Python 3.13

Python

Características Modernas

Operador Walrus

Python

Características Modernas

Pattern Matching

Python

Características Modernas

Instalación Beautiful Soup

Python

Web Scraping

Sintaxis General De Beautiful Soup

Python

Web Scraping

Tipos De Selectores

Python

Web Scraping

Web Scraping De Html

Python

Web Scraping

Web Scraping Para Ciencia De Datos

Python

Web Scraping

Autenticación Y Acceso A Recursos Protegidos

Python

Web Scraping

Combinación De Selenium Con Beautiful Soup

Python

Web Scraping

Accede GRATIS a Python y certifícate

Ejercicios de programación de Python

Evalúa tus conocimientos de esta lección Módulo re con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.

Módulo math

Python
Puzzle

Reto herencia

Python
Código

Excepciones

Python
Test

Introducción a Python

Python
Test

Reto variables

Python
Código

Funciones Python

Python
Puzzle

Reto funciones

Python
Código

Módulo datetime

Python
Test

Reto acumulación

Python
Código

Reto estructuras condicionales

Python
Código

Polimorfismo

Python
Test

Módulo os

Python
Test

Reto métodos dunder

Python
Código

Diccionarios

Python
Puzzle

Reto clases y objetos

Python
Código

Reto operadores

Python
Código

Operadores

Python
Test

Estructuras de control

Python
Puzzle

Funciones lambda

Python
Test

Reto diccionarios

Python
Código

Reto función lambda

Python
Código

Encapsulación

Python
Puzzle

Reto coleciones

Python
Proyecto

Reto funciones auxiliares

Python
Código

Crear módulos y paquetes

Python
Puzzle

Módulo datetime

Python
Puzzle

Excepciones

Python
Puzzle

Operadores

Python
Puzzle

Diccionarios

Python
Test

Reto map, filter

Python
Código

Reto tuplas

Python
Código

Proyecto gestor de tareas CRUD

Python
Proyecto

Tuplas

Python
Puzzle

Variables

Python
Puzzle

Tipos de datos

Python
Puzzle

Conjuntos

Python
Test

Reto mixins

Python
Código

Módulo csv

Python
Test

Módulo json

Python
Test

Herencia

Python
Test

Análisis de datos de ventas con Pandas

Python
Proyecto

Reto fechas y tiempo

Python
Proyecto

Reto estructuras de iteración

Python
Código

Funciones

Python
Test

Reto comprehensions

Python
Código

Variables

Python
Test

Reto serialización

Python
Proyecto

Módulo csv

Python
Puzzle

Reto polimorfismo

Python
Código

Polimorfismo

Python
Puzzle

Clases y objetos

Python
Código

Reto encapsulación

Python
Código

Estructuras de control

Python
Test

Importar módulos y paquetes

Python
Test

Módulo math

Python
Test

Funciones lambda

Python
Puzzle

Reto excepciones

Python
Código

Listas

Python
Puzzle

Reto archivos

Python
Proyecto

Encapsulación

Python
Test

Reto conjuntos

Python
Código

Clases y objetos

Python
Test

Instalación de Python y creación de proyecto

Python
Test

Reto listas

Python
Código

Tipos de datos

Python
Test

Crear módulos y paquetes

Python
Test

Tuplas

Python
Test

Herencia

Python
Puzzle

Reto acceso a sistema

Python
Proyecto

Proyecto sintaxis calculadora

Python
Proyecto

Importar módulos y paquetes

Python
Puzzle

Clases y objetos

Python
Puzzle

Módulo os

Python
Puzzle

Listas

Python
Test

Conjuntos

Python
Puzzle

Reto tipos de datos

Python
Código

Reto matemáticas

Python
Proyecto

Módulo json

Python
Puzzle

En esta lección

Objetivos de aprendizaje de esta lección

  • Comprender los conceptos básicos de expresiones regulares y su uso con el módulo re en Python.
  • Aprender a construir patrones con caracteres literales, clases predefinidas, anclas y cuantificadores.
  • Dominar la creación y uso de grupos de captura, incluyendo grupos nombrados y no capturantes.
  • Utilizar las funciones principales de búsqueda y reemplazo del módulo re para manipular texto.
  • Aplicar expresiones regulares para validar, extraer y transformar datos en diferentes contextos prácticos.