Las expresiones regulares, comúnmente abreviadas como regex o regexp, son herramientas poderosas para la búsqueda de patrones y la manipulación de texto. Su función principal es permitir la identificación y extracción de cadenas de texto que cumplen con ciertos criterios predefinidos. No son exclusivas de Python; este concepto es fundamental en muchos lenguajes de programación y herramientas de línea de comandos.
En Python, el módulo re proporciona soporte para trabajar con expresiones regulares. Este módulo ofrece funciones para buscar, reemplazar y dividir cadenas de texto utilizando patrones complejos.
Uso Básico: Validación de Entrada con el Módulo re
Consideremos un escenario donde necesitamos validar que el usuario ingrese un número de identificación compuesto exactamente por una letra mayúscula seguida de nueve dígitos. Sin expresiones regulares, esta validación podría ser tediosa y propensa a errores. Con regex, se simplifica enormemente:
import re
def validar_identificador(identificador: str) -> bool:
"""
Valida si un identificador sigue el patrón: una letra mayúscula,
seguida de nueve dígitos.
Ej: A123456789
"""
# ^ indica el inicio de la cadena
# [A-Z] busca una letra mayúscula
# \d{9} busca exactamente nueve dígitos
# $ indica el final de la cadena
patron_id = r'^[A-Z]\d{9}$'
# re.match intenta aplicar el patrón desde el inicio de la cadena.
return bool(re.match(patron_id, identificador))
# Ejemplos de uso
id_valido_ej = "X987654321"
id_invalido_letras_ej = "AX987654321" # Demasiados caracteres al principio
id_invalido_digitos_ej = "B123" # Pocos dígitos
id_invalido_formato_ej = "c123456789" # Minúscula
print(f"'{id_valido_ej}' es válido: {validar_identificador(id_valido_ej)}")
print(f"'{id_invalido_letras_ej}' es válido: {validar_identificador(id_invalido_letras_ej)}")
print(f"'{id_invalido_digitos_ej}' es válido: {validar_identificador(id_invalido_digitos_ej)}")
print(f"'{id_invalido_formato_ej}' es válido: {validar_identificador(id_invalido_formato_ej)}")
Conjuntos de Caracteres
Los corchetes [] definen un conjunto de caracteres, donde se buscará la coincidencia con cualquiera de los caracteres dentro del conjunto.
[0-9]: Coincide con cualquier dígito del 0 al 9.[a-z]: Coincide con cualquier letra minúscula de la 'a' a la 'z'.[A-Z]: Coincide con cualquier letra mayúscula de la 'A' a la 'Z'.[0-9a-zA-Z]: Coincide con cualquier dígito, letra minúscula o mayúscula.[aeiou]: Coincide con cualquier vocal minúscula.[^aeiou]: Coincide con cualquier carácter excepto una vocal minúscula (el acento circunflejo^dentro de los corchetes niega el conjunto).
Metacaracteres y Caracteres Especiales
Además de los conjuntos de caracteres, las expresiones regulares utilizan metacaracteres que tienen significados especiales:
.: Coincide con cualquier carácter, excepto el salto de línea.\w: Coincide con cualquier carácter alfanumérico (letras, números y guion bajo:[a-zA-Z0-9_]).\W: Coincide con cualquier carácter no alfanumérico (lo opuesto a\w).^: Coincide con el inicio de la cadena.$: Cioncide con el final de la cadena.|: Funciona como un "O" lógico. Por ejemplo,"manzana|pera"coincide con "manzana" o "pera".(): Se utiliza para agrupar patrones y crear "grupos de captura".\d: Conicide con cualquier dígito (equivalente a[0-9]).\D: Coincide con cualquier carácter no dígito (equivalente a[^0-9]).\s: Coincide con cualquier carácter de espacio en blanco (espacio, tabulación, salto de línea, etc.).\S: Coincide con cualquier carácter no espacio en blanco.
Cuantificadores
Los cuantificadores se usan para especificar cuántas veces debe aparecer un carácter, grupo o conjunto de caracteres. Todos los cuantificadores son "codiciosos" (greedy) por defecto, lo que significa que intentarán coincidir con la mayor cantidad de texto posible.
*: Coincide con cero o más ocurrencias del elemento precedente.+: Coincide con una o más ocurrencias del elemento precedente.?: Coincide con cero o una ocurrencia del elemento precedente.{n}: Coincide exactamentenveces.{n,}: Coincideno más veces.{n,m}: Coincide entrenymveces (inclusive).
Coincidencia Codiciosa (Greedy) vs. No Codiciosa (Non-Greedy)
Como se mencionó, los cuantificadores son codiciosos por defecto, lo que a veces no es el comportamiento deseado. Para hacer un cuantificador "no codicioso" (también conocido como "reacio" o "perezoso"), simplemente se añade un signo de interrogación ? después del cuantificador.
import re
texto_html = "<b>Esto está en negrita</b> y <i>esto en cursiva</i>"
# Coincidencia codiciosa (greedy)
# <.*> intentará coincidir desde el primer < hasta el ÚLTIMO >
patron_greedy = r'<.*>'
print("Patrón Greedy:")
print(re.findall(patron_greedy, texto_html)) # Resultado: ['<b>Esto está en negrita</b> y <i>esto en cursiva</i>']
print("-" * 30)
# Coincidencia no codiciosa (non-greedy)
# <.*?> intentará coincidir desde el primer < hasta el PRIMER >
patron_non_greedy = r'<.*?>'
print("Patrón Non-Greedy:")
print(re.findall(patron_non_greedy, texto_html)) # Resultado: ['<b>', '</b>', '<i>', '</i>']
En el ejemplo anterior, el patrón codicioso <.*> consume la mayor cantidad de caracteres posible, abarcando desde la primera etiqueta de apertura hasta la última de cierre. En contraste, el patrón no codicioso <.*?> se detiene en la primera etiqueta de cierre que encuentra, capturando cada par de etiquetas de forma individual.
Escape de Caracteres Especiales
Algunos caracteres como ., *, +, ?, ^, $, |, (), [], {} y \ tienen un significado especial en expresiones regulares. Si se desea buscar uno de estos caracteres literalmente, se debe "escapar" con una barra invertida \.
- Para buscar un punto literal:
\. - Para buscar un asterisco literal:
\* - Para buscar una barra invertida literal:
\\
En Python, es una buena práctica usar cadenas "raw" (cadenas crudas), prefijadas con r (por ejemplo, r'\n'), al definir patrones de expresiones regulares. Esto evita que Python interprete las barras invertidas como secuencias de escape de cadena, pasando la secuencia directamente al motor de expresiones regulares.
Ejemplos Prácticos de Expresiones Regulares
Aquí se presentan algunas expresiones regulares comunes para la validación de formatos:
- Número de Teléfono (ej. 10 dígitos): ```
^\d{10}$
Coincide con una cadena que contiene exactamente 10 dígitos. - Identificador Alfanumérico (ej. 8-15 caracteres): ```
^[A-Z0-9]{8,15}$
Coincide con una cadena que empieza y termina con 8 a 15 caracteres, que pueden ser letras mayúsculas o números. - Correo Electrónico Básico: ```
^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$
Este patrón busca un formato de correo electrónico común: caracteres alfanuméricos, puntos, guiones bajos, porcentajes, signos más o menos, seguidos de un '@', luego más caracteres alfanuméricos, puntos o guiones, y finalmente un punto seguido de al menos dos letras (dominio de nivel superior). - Código de Producto (ej. 6-12 dígitos): ```
^\d{6,12}$
Coincide con una cadena que consiste únicamente en 6 a 12 dígitos.
Es importante recordar que los patrones de expresiones regulares pueden variar significativamente según los requisitos específicos y las normativas locales (por ejemplo, formatos de números de teléfono o identificaciones de un país a otro).