Expressões regulares são padrões usados para buscar texto.
Elas permitem encontrar, extrair e substituir substrings.
Primeiramente, dominar regex é uma habilidade valiosa.
Com poucos símbolos, fazemos buscas complexas.
Por exemplo, \d{3}-\d{3} encontra formatos como “123-456”.
Sem regex, isso exigiria várias linhas de código.
Além disso, regex funciona em muitas linguagens.
Python, JavaScript, Java e PHP suportam o mesmo padrão.
Portanto, o conhecimento é portável entre ecossistemas.
No Python, usamos o módulo re nativo.
Assim, você pode validar emails, CPFs, telefones e mais.
Essa ferramenta foi projetada para eficiência e precisão.
Características fundamentais das expressões regulares
Uma regex é construída com metacaracteres especiais.
O ponto (.) significa qualquer caractere (exceto quebra).
O asterisco (*) repete o padrão zero ou mais vezes.
O mais (+) repete uma ou mais vezes.
A interrogação (?) torna algo opcional.
Colchetes [abc] indicam “um destes caracteres”.
Barras invertidas criam classes como \d (dígitos) ou \w (letras/números).
Isso foi inspirado na teoria de linguagens formais.
Uma fórmula que representa uma regex básica é:
Outra característica importante são os grupos e capturas.
Parênteses () agrupam partes do padrão.
Eles também capturam o texto correspondente.
Você pode referenciar grupos por números ou nomes.
Isso é útil para extrair partes específicas de um texto.
Por exemplo, capturar dia, mês e ano de uma data.
Consequentemente, você processa dados estruturados dentro de texto bruto.
Metacaracteres mais úteis e suas funções
Os metacaracteres são o coração das expressões regulares.
O símbolo ^ ancora no início da string.
O símbolo $ ancora no final da string.
A barra vertical | funciona como OU lógico.
Por exemplo, gato|cão encontra qualquer um deles.
Colchetes com hífen criam intervalos: [a-z] são letras minúsculas.
O metacaractere \b indica borda de palavra.
Isso é útil para buscar palavras inteiras, não substrings.
Além disso, \B é o oposto (não borda).
Quantificadores como {n,m} controlam repetições exatas.
Por exemplo, \d{2,4} encontra 2 a 4 dígitos.
Portanto, dominar esses símbolos é fundamental.
Outro grupo importante são os atalhos pré-definidos.
\D corresponde a qualquer não-dígito.
\W corresponde a qualquer não-letra/número.
\S corresponde a qualquer não-espaço.
Eles são úteis para negar classes de caracteres.
Por exemplo, \D+ captura tudo que não é número.
Use esses atalhos para limpar dados rapidamente.
Isso foi projetado para tornar regex mais legível.
Primeiramente, decore os atalhos mais comuns.
Depois, use tabelas de consulta para os raros.
Assim, você escreve padrões mais expressivos.
Quando utilizar expressões regulares no dia a dia
Use regex para validação de formatos conhecidos. E-mails, URLs, placas de carro e CPF são exemplos. Também são ótimas para substituições complexas em massa. Por exemplo, trocar todos os números de telefone em um texto. Outro bom uso é para extração de dados em logs. Arquivos de servidor ou sistemas legacy são ideais. Além disso, regex ajuda na limpeza de dados textuais. Por outro lado, evite regex para HTML ou XML aninhados. Esses formatos não são regulares (contexto livre). Use parsers dedicados como BeautifulSoup nesses casos. Primeiramente, avalie se o padrão é linear. Se for, regex é sua melhor ferramenta. Portanto, regex é poderosa, mas não para tudo.
Outro bom uso é na busca dentro de editores de texto. VS Code, Sublime e Vim suportam regex nas buscas. Isso acelera drasticamente refatorações de código. Use também em pipelines de processamento de dados. Apache Spark e Pandas aceitam regex para filtros. Isso foi amplamente adotado na engenharia de dados. Portanto, regex é um curinga para muitos problemas.
Boas práticas e armadilhas comuns
Sempre use strings raw r"..." para evitar escapes duplicados.
Isso torna a regex muito mais legível e segura.
Outra boa prática é compilar padrões reutilizáveis com re.compile().
Isso melhora a performance em loops grandes.
Além disso, comente regexes complexas com detalhes.
Use o modo verbose (re.VERBOSE) para isso.
Ele permite espaços e comentários dentro do padrão.
Uma armadilha comum é o greedy vs non-greedy.
Por padrão, quantificadores capturam o máximo possível.
Use *? ou +? para captura mínima (lazy).
Isso foi projetado para evitar capturar mais do que se deseja.
Portanto, teste sempre com vários casos de borda.
Outra armadilha é esquecer de escapar caracteres literais.
Ponto, colchetes, parênteses e asterisco precisam de \.
Esqueça isso e sua regex terá comportamento inesperado.
Além disso, evite regex excessivamente longas e aninhadas.
Elas são difíceis de depurar e manter no futuro.
Primeiramente, divida problemas complexos em etapas menores.
Use variáveis para construir padrões aos poucos.
Teste cada parte separadamente antes de combinar.
Assim, você mantém a sanidade mental do programador.
Portanto, documente e teste suas expressões regulares sempre.
Exemplo prático: validação e extração com re
O código abaixo demonstra os principais usos do módulo re.
Primeiro, validamos formatos comuns como e-mail e telefone.
Depois, extraímos partes específicas de um texto.
Também mostramos substituições em massa expressivas.
Usamos também flags para buscas case-insensitive.
Por fim, otimizamos padrões com compilação prévia.
Observe como poucas linhas resolvem problemas complexos.
Sem regex, o mesmo código teria muitas condições.
Vamos ao código comentado com vários exemplos práticos.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
import re # ============================================ # EXEMPLO 1: VALIDAÇÃO DE FORMATOS # ============================================ print("=== Validação de Formatos ===") # Validar e-mail simples (versão educacional) email_padrao = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$' emails_teste = [ "usuario@email.com", "nome.sobrenome@empresa.com.br", "invalido@", "sem_arroba.com", "123@456.789" ] for email in emails_teste: if re.match(email_padrao, email): print(f"✅ Válido: {email}") else: print(f"❌ Inválido: {email}") # Validar telefone brasileiro (com ou sem DDD) telefone_padrao = r'^(\(?\d{2}\)?\s?)?9?\d{4}-\d{4}$' telefones = [ "(11) 91234-5678", "11912345678", "91234-5678", "1234-5678", # inválido (celular precisa do 9) "(11) 1234-5678" ] print("\n=== Validação de Telefones ===") for tel in telefones: if re.match(telefone_padrao, tel): print(f"✅ Válido: {tel}") else: print(f"❌ Inválido: {tel}") # ============================================ # EXEMPLO 2: EXTRAÇÃO DE DADOS # ============================================ print("\n=== Extração de Dados ===") texto = """ Data: 2024-01-15, venda de R$ 1.234,56 para cliente Ana. Em 2024-02-20, valor de R$ 2.500,00 para Carlos. Total do mês: R$ 12.345,67 """ # Extrair todas as datas no formato YYYY-MM-DD datas = re.findall(r'\d{4}-\d{2}-\d{2}', texto) print(f"Datas encontradas: {datas}") # Extrair valores monetários (R$ 1.234,56) valores = re.findall(r'R\$ [\d\.]+,\d{2}', texto) print(f"Valores encontrados: {valores}") # Extrair usando grupos (captura) padrao_data_grupo = r'(\d{4})-(\d{2})-(\d{2})' for data in re.finditer(padrao_data_grupo, texto): ano, mes, dia = data.groups() print(f"Data capturada -> Ano: {ano}, Mês: {mes}, Dia: {dia}") # Nomear grupos (Python 3.8+) padrao_nomeado = r'(?P<dia>\d{2})/(?P<mes>\d{2})/(?P<ano>\d{4})' texto_data_br = "Ontem foi 15/03/2024 e hoje é 16/03/2024" for match in re.finditer(padrao_nomeado, texto_data_br): print(f"Dia: {match.group('dia')}, Mês: {match.group('mes')}, Ano: {match.group('ano')}") # ============================================ # EXEMPLO 3: SUBSTITUIÇÕES COM re.sub() # ============================================ print("\n=== Substituições ===") # Esconder e-mails texto_emails = "Contato: ana@email.com ou carlos@empresa.com.br" anonimizado = re.sub(r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}', '[EMAIL OCULTO]', texto_emails) print(f"Original: {texto_emails}") print(f"Anonimizado: {anonimizado}") # Limpar números de uma string texto_sujo = "Pedido #1234 - Valor R$ 567,89" apenas_numeros = re.sub(r'[^0-9]', '', texto_sujo) print(f"Apenas números: {apenas_numeros}") # Converter datas BR para ISO (função com re.sub) def converter_iso(match): dia, mes, ano = match.groups() return f"{ano}-{mes}-{dia}" texto_datas = "15/03/2024 e 20/12/2023" iso_datas = re.sub(r'(\d{2})/(\d{2})/(\d{4})', converter_iso, texto_datas) print(f"Datas em ISO: {iso_datas}") # ============================================ # EXEMPLO 4: FLAGS E COMPILAÇÃO # ============================================ print("\n=== Flags e Compilação ===") # Case-insensitive (IGNORECASE) texto_exemplo = "Python é PYTHON poderoso. python também." python_comp = re.findall(r'python', texto_exemplo, re.IGNORECASE) print(f"Pythons encontrados: {python_comp}") # Busca multilinha (MULTILINE) codigo = """ def funcao(): pass class Teste: pass """ # Encontrar linhas que começam com def ou class padrao_inicio = r'^(def|class)\s+\w+' encontrados = re.findall(padrao_inicio, codigo, re.MULTILINE) print(f"Definições encontradas: {encontrados}") # Compilar padrão para reutilização padrao_compilado = re.compile(r'\b\w{3,5}\b', re.IGNORECASE) palavras = padrao_compilado.findall("Python regex é muito útil para buscas complexas") print(f"Palavras com 3-5 letras: {palavras}") # ============================================ # EXEMPLO 5: EXEMPLOS PRÁTICOS COMUNS # ============================================ print("\n=== Exemplos Práticos ===") # Extrair todas as URLs de um texto texto_urls = "Visite https://python.org e http://example.com ou www.google.com" url_padrao = r'https?://[a-zA-Z0-9./-]+|www\.[a-zA-Z0-9./-]+' urls = re.findall(url_padrao, texto_urls) print(f"URLs encontradas: {urls}") # Validar CPF (formato apenas, sem dígito verificador) cpf_padrao = r'^\d{3}\.\d{3}\.\d{3}-\d{2}$' cpfs = ["123.456.789-00", "11122233344", "abc.def.ghi-jk"] for cpf in cpfs: if re.match(cpf_padrao, cpf): print(f"✅ CPF válido: {cpf}") else: print(f"❌ CPF inválido: {cpf}") # Separar palavra em sílabas simples (educacional) palavra = "programacao" silabas = re.findall(r'[bcdfghjklmnpqrstvwyxz]*[aeiouáéíóú]+', palavra) print(f"Sílabas de '{palavra}': {silabas}") # Limpar caracteres especiais texto_sujo = "Olá, como você está? Hoje é 15/03!" limpo = re.sub(r'[^\w\s]', '', texto_sujo, encoding='utf-8') print(f"Texto limpo (apenas letras/ números/ espaços): {limpo}") |
Os exemplos mostram a versatilidade das expressões regulares.
Com poucas linhas, resolvemos problemas complexos.
Primeiramente, note os padrões com metacaracteres \d e \w.
Eles simplificam muito a escrita das regexes.
Além disso, as flags como re.IGNORECASE aumentam a flexibilidade.
A compilação prévia com re.compile() melhora a performance.
Isso é útil quando o mesmo padrão é usado várias vezes.
Para validações em formulários, use re.match() ou re.fullmatch().
Para extrações repetidas, finditer() é mais eficiente.
Portanto, escolha a função certa para cada tarefa.
Isso foi pensado para otimizar o uso de memória e tempo.
Outro ponto crucial é o tratamento de caracteres especiais.
Pontos, colchetes e parênteses precisam de escape com barra invertida.
Por exemplo, \. busca um ponto literal.
Esqueça isso e sua regex terá comportamento inesperado.
Além disso, evite regex excessivamente longas.
Elas são difíceis de depurar e manter.
Primeiramente, divida problemas complexos em etapas.
Use variáveis para construir padrões aos poucos.
Comente suas regexes com detalhes significativos.
No Python, use strings raw r"..." para evitar escapes duplicados.
Assim, você mantém a sanidade mental do programador.
Portanto, documente suas expressões regulares sempre.
. – qualquer caractere\d – dígito (0-9)\w – letra, número ou _\s – espaço, tab ou quebra^ – início da string$ – fim da string* – zero ou mais+ – um ou mais? – zero ou um{n,m} – entre n e m vezes
Finalmente, lembre-se dos limites das expressões regulares. Elas não conseguem contar parênteses aninhados corretamente. Também falham em linguagens com palavras balanceadas. Para esses casos, use analisadores sintáticos específicos. Um exemplo clássico é HTML dentro de HTML. Regex não é a ferramenta correta para isso. Portanto, conheça o domínio do seu problema. Use regex para padrões regulares (daí o nome). Isso foi estabelecido pela teoria da computação. Respeite esses limites e você será bem-sucedido. Assim, regex será uma aliada, não uma dor de cabeça.