Expressões regulares (Regex) funcionam como uma "faca suíça" para o processamento de texto. Emmbora sua sintaxe possa parecer intimidadora à primeira vista, dominar essa ferramenta permite que desenvolvedores Python criem scripts de automação robustos para extrair informações, validar dados e manipular strings com eficiência.
Fundamentos do Módulo re
No Python, a biblioteca padrão re é a porta de entrada para trabalhar com padrões de busca. Diferente dos métodos de string convencionais, o Regex permite buscas baseadas em regras complexas.
import re
# Exemplo básico de busca
conteudo = "Entre em contato através do email suporte@empresa.com.br hoje mesmo."
padrao_email = r'[\w.-]+@[\w.-]+\.[a-zA-Z]{2,}'
busca = re.search(padrao_email, conteudo)
if busca:
print(f"Email detectado: {busca.group()}")
# Comparativo entre métodos principais
amostra = "ID: 450, Valor: R$ 1250.50, Data: 2023-10-25"
# search: Localiza a primeira ocorrência
primeiro_numero = re.search(r'\d+', amostra)
print(f"Primeiro número: {primeiro_numero.group()}") # 450
# findall: Retorna uma lista com todas as ocorrências
todos_numeros = re.findall(r'\d+', amostra)
print(f"Lista completa: {todos_numeros}") # ['450', '1250', '50', '2023', '10', '25']
# finditer: Ideal para processar grandes volumes (retorna iterador)
for item in re.finditer(r'\d{4}-\d{2}-\d{2}', amostra):
print(f"Data encontrada na posição {item.span()}: {item.group()}")
Classes de Caracteres e Atalhos
Para construir padrões eficientes, utilizamos metacaracteres que representam grupos de caracteres:
\d: Qualquer dígito numérico (0-9).\w: Caracteres alfanuméricos e sublinhado (_).\s: Espaços em branco, tabs e quebras de linha..: Qualquer caractere, exceto nova linha.[A-Z]: Qualquer letra maiúscula.
# Exemplo de captura com grupos
registro = "ACESSO_WEB - Usuario: admin123 - Prioridade: ALTA"
padrao_usuario = r"Usuario: (\w+) - Prioridade: (\w+)"
match = re.search(padrao_usuario, registro)
if match:
# O group(0) é a correspondência completa, 1 e 2 são os grupos ()
print(f"Username: {match.group(1)}")
print(f"Nível: {match.group(2)}")
Aplicações Reais em Scripts de Automação
1. Análise de Logs do Sistema
Scripts de monitoramento frequentemente precisam filtrar arquivos de log para identificar falhas críticas.
import re
from collections import Counter
logs_servidor = """
[2023-11-01 08:00:01] INFO: Sistema iniciado
[2023-11-01 08:05:22] ERROR: Falha na conexão com banco (Timeout)
[2023-11-01 08:06:45] WARNING: Latência alta detectada
[2023-11-01 08:10:12] ERROR: Autenticação negada para user 'guest'
"""
def processar_logs(texto):
# Padrão: [data] NÍVEL: Mensagem
regex_log = r'\[(?P<data>.*?)\] (?P<nivel>[A-Z]+): (?P<msg>.*)'
erros = []
contagem_niveis = Counter()
for linha in texto.strip().split('\n'):
m = re.match(regex_log, linha)
if m:
nivel = m.group('nivel')
contagem_niveis[nivel] += 1
if nivel == 'ERROR':
erros.append(m.group('msg'))
return contagem_niveis, erros
resumo, lista_erros = processar_logs(logs_servidor)
print(f"Resumo: {dict(resumo)}")
print(f"Mensagens de erro: {lista_erros}")
2. Renomeação em Massa de Arquivos
Utilizar Regex para limpar nomes de aqruivos recebidos de fontes externas ou backups.
import re
import os
def normalizar_arquivos(diretorio, padrao_busca, novo_formato):
# Exemplo: Transformar "DOC_2023_RELATORIO.pdf" em "RELATORIO_2023.pdf"
for nome_antigo in os.listdir(diretorio):
if re.search(padrao_busca, nome_antigo):
nome_novo = re.sub(padrao_busca, novo_formato, nome_antigo)
print(f"Renomeando: {nome_antigo} -> {nome_novo}")
# os.rename(os.path.join(diretorio, nome_antigo), os.path.join(diretorio, nome_novo))
# Uso: Captura o ano e o nome, inverte a ordem
# padrao = r"DOC_(\d{4})_(.*)\.pdf"
# normalizar_arquivos("./docs", padrao, r"\2_\1.pdf")
3. Validação e Higienização de Dados
Garantir que os dados inseridos em um sistema seguem o formato esperado.
def limpar_telefone(tel_bruto):
# Remove tudo que não for dígito
apenas_numeros = re.sub(r'\D', '', tel_bruto)
# Valida formato brasileiro (ex: 11988887777 ou 1133334444)
if re.match(r'^\d{10,11}$', apenas_numeros):
return apenas_numeros
return None
telefones = ["(11) 98888-7777", "11 3333 4444", "abc-1234"]
validados = [limpar_telefone(t) for t in telefones]
print(f"Telefones limpos: {validados}")
Recursos Avançados
Lookarounds (Âncoras de Contexto)
Permite validar se um padrão é precedido ou seguido por outro, sem incluir esses caracteres no resultado da captura.
# Lookahead Positivo (?=...) - Busca valor seguido de ' USD'
precos = "Produto A: 100 USD, Produto B: 250 EUR"
valores_dolar = re.findall(r'\d+(?= USD)', precos)
print(valores_dolar) # ['100']
# Lookbehind Positivo (?<=...) - Busca dígitos precedidos por 'ID-'
ids_texto = "ID-550, ID-920, REF-100"
numeros_id = re.findall(r'(?<=ID-)\d+', ids_texto)
print(numeros_id) # ['550', '920']
Compilação de Padrões
Se uma expressão será executada milhares de vezes em um loop, compilá-la aumenta a performence.
# Pré-compilação para reuso
REG_CPF = re.compile(r'\d{3}\.\d{3}\.\d{3}-\d{2}')
lista_cpfs = ["123.456.789-00", "000.111.222-33"]
for cpf in lista_cpfs:
if REG_CPF.match(cpf):
print(f"{cpf} é válido.")
Resumo de Sintaxe
| Símbolo | Descrição | Exemplo |
|---|---|---|
^ / $ |
Início / Fim da string | ^Log |
+ / * |
1 ou mais / 0 ou mais ocorrências | \d+ |
? |
0 ou 1 ocorrência (ou torna o quantificador não-guloso) | https? |
{n,m} |
De n a m repetições | \d{2,4} |
| |
Operador OU | (jpg|png|gif) |
[] |
Conjunto de caracteres específicos | [aeiou] |
Embora poderosas, as expressões regulares devem ser usadas com cautela. Para manipulações simples como trocar extensões de arquivos ou converter cases, os métodos nativos .split(), .replace() e .startswith() costumam ser mais legíveis e performáticos.