Voltar ao Glossario
Glossario Python

Regex: O que É e Como Funciona | Python Brasil

Domine expressoes regulares em Python com o modulo re: padroes, metacaracteres, grupos, substituicao e boas praticas para validacao e busca de texto.

O que e Regex?

Regex (expressao regular) e uma sequencia de caracteres que define um padrao de busca em texto. Em Python, expressoes regulares sao manipuladas pelo modulo embutido re. Elas sao uma ferramenta poderosa para validacao de dados, busca de padroes, extracao de informacoes e substituicao de texto. Embora a sintaxe possa parecer intimidadora no inicio, dominar regex e uma habilidade valiosa para qualquer programador.

Funcoes Principais do Modulo re

import re

texto = 'Meu telefone e (11) 98765-4321 e meu email e ana@python.dev.br'

# re.search — encontra a PRIMEIRA ocorrencia
match = re.search(r'\d{5}-\d{4}', texto)
if match:
    print(match.group())  # 98765-4321
    print(match.start())  # posicao inicial
    print(match.end())    # posicao final

# re.findall — encontra TODAS as ocorrencias
numeros = re.findall(r'\d+', texto)
print(numeros)  # ['11', '98765', '4321']

# re.finditer — retorna iterador de objetos Match
for m in re.finditer(r'\d+', texto):
    print(f'{m.group()} na posicao {m.start()}')

# re.match — verifica apenas o INICIO da string
resultado = re.match(r'Meu', texto)
print(resultado.group())  # 'Meu'

# re.fullmatch — verifica se a string INTEIRA corresponde
print(re.fullmatch(r'\d+', '12345'))   # Match
print(re.fullmatch(r'\d+', '123abc'))  # None

# re.sub — substituicao
censurado = re.sub(r'\d', '*', texto)
print(censurado)  # 'Meu telefone e (**) *****-**** e meu email e ana@python.dev.br'

# re.split — dividir por padrao
partes = re.split(r'[,;\s]+', 'um, dois; tres    quatro')
print(partes)  # ['um', 'dois', 'tres', 'quatro']

Metacaracteres Essenciais

import re

# . — qualquer caractere (exceto nova linha)
print(re.findall(r'P..hon', 'Python Pithon Pothon'))  # ['Python', 'Pithon', 'Pothon']

# \d — digito, \D — nao-digito
# \w — alfanumerico + _, \W — nao-alfanumerico
# \s — espaco em branco, \S — nao-espaco

# ^ — inicio da string, $ — final da string
print(re.search(r'^\d+', '123abc'))   # Match '123'
print(re.search(r'\d+$', 'abc123'))   # Match '123'

# Quantificadores
# * — zero ou mais
# + — um ou mais
# ? — zero ou um
# {n} — exatamente n
# {n,m} — de n a m

print(re.findall(r'\d{2,4}', 'a1 bc23 def456 ghij7890'))
# ['23', '456', '7890']

# Quantificadores preguicosos (lazy) vs gananciosos (greedy)
html = '<b>negrito</b> e <i>italico</i>'
print(re.findall(r'<.*>', html))    # ['<b>negrito</b> e <i>italico</i>'] — ganancioso
print(re.findall(r'<.*?>', html))   # ['<b>', '</b>', '<i>', '</i>'] — preguicoso

Classes de Caracteres

import re

# Colchetes definem classes de caracteres
print(re.findall(r'[aeiou]', 'Python Brasil'))  # vogais minusculas
print(re.findall(r'[A-Z]', 'Python Brasil'))    # letras maiusculas
print(re.findall(r'[0-9a-f]+', 'cor: #ff5733')) # hexadecimais

# Negacao com ^
print(re.findall(r'[^0-9]', 'abc123'))  # ['a', 'b', 'c']

# Alternativa com |
print(re.findall(r'gato|cachorro', 'Tenho um gato e um cachorro'))

Grupos de Captura

import re

# Grupos com parenteses
texto = 'Nome: Ana Silva, Idade: 28'
match = re.search(r'Nome: (\w+ \w+), Idade: (\d+)', texto)
if match:
    print(match.group(0))  # 'Nome: Ana Silva, Idade: 28' — match completo
    print(match.group(1))  # 'Ana Silva'
    print(match.group(2))  # '28'
    print(match.groups())  # ('Ana Silva', '28')

# Grupos nomeados
padrao = r'(?P<nome>\w+ \w+).*?(?P<idade>\d+)'
match = re.search(padrao, texto)
if match:
    print(match.group('nome'))   # 'Ana Silva'
    print(match.group('idade'))  # '28'
    print(match.groupdict())     # {'nome': 'Ana Silva', 'idade': '28'}

# Grupo nao-capturante
resultado = re.findall(r'(?:https?://)?(\w+\.com\.br)', 'Acesse https://python.com.br')
print(resultado)  # ['python.com.br']

# Backreference
duplicadas = re.findall(r'\b(\w+)\s+\1\b', 'o o gato gato sentou')
print(duplicadas)  # ['o', 'gato']

Compilacao de Padroes

Para padroes usados repetidamente, compile-os para melhor desempenho.

import re

# Compilando padrao
padrao_email = re.compile(r'[\w.+-]+@[\w-]+\.[\w.]+')

emails = [
    'ana@email.com',
    'invalido@',
    'bruno.silva@empresa.com.br',
    'nao-email',
]

for e in emails:
    if padrao_email.fullmatch(e):
        print(f'Valido: {e}')
    else:
        print(f'Invalido: {e}')

# Flags de compilacao
padrao = re.compile(r'python', re.IGNORECASE)
print(padrao.findall('Python PYTHON python'))  # ['Python', 'PYTHON', 'python']

# Flag VERBOSE para padroes legiveis
padrao_cpf = re.compile(r"""
    ^\d{3}      # tres primeiros digitos
    \.          # ponto literal
    \d{3}       # tres digitos do meio
    \.          # ponto literal
    \d{3}       # tres ultimos digitos
    -           # hifen
    \d{2}$      # digitos verificadores
""", re.VERBOSE)

Validacoes Praticas

import re

def validar_cpf_formato(cpf: str) -> bool:
    """Valida o formato do CPF (nao verifica digitos)."""
    return bool(re.fullmatch(r'\d{3}\.\d{3}\.\d{3}-\d{2}', cpf))

def validar_telefone(telefone: str) -> bool:
    """Valida telefone brasileiro com DDD."""
    padrao = r'\(?\d{2}\)?\s?\d{4,5}-?\d{4}'
    return bool(re.fullmatch(padrao, telefone))

def extrair_hashtags(texto: str) -> list[str]:
    """Extrai hashtags de um texto."""
    return re.findall(r'#(\w+)', texto)

# Substituicao com funcao
def censurar_emails(texto: str) -> str:
    def ocultar(match):
        email = match.group()
        usuario, dominio = email.split('@')
        return f'{usuario[0]}***@{dominio}'
    return re.sub(r'[\w.+-]+@[\w-]+\.[\w.]+', ocultar, texto)

print(censurar_emails('Contato: ana.silva@email.com'))
# 'Contato: a***@email.com'

Erros Comuns

O erro mais comum e esquecer de usar raw strings (r'...'), fazendo com que o Python interprete barras invertidas antes do regex. Outro erro e usar regex para tarefas simples que str.split(), str.replace() ou in resolveriam melhor. Tambem e frequente nao tratar o retorno None de re.search(), causando AttributeError ao chamar .group(). O uso de quantificadores gananciosos em vez de preguicosos tambem gera resultados inesperados com frequencia.

Boas Praticas

Sempre use raw strings para padroes regex. Compile padroes que serao reutilizados. Use a flag re.VERBOSE para padroes complexos. Prefira metodos de string simples quando regex nao for necessario. Teste seus padroes com ferramentas interativas antes de integrar ao codigo. Documente padroes complexos com comentarios.

Quando Usar

Regex e ideal para validacao de formatos, extracao de dados estruturados de texto, busca com padroes complexos e substituicao avancada. Para parsing de HTML ou XML, prefira bibliotecas especializadas como BeautifulSoup ou lxml.