---
title: "Regex: O que É e Como Funciona | Python Brasil"
url: "https://python.dev.br/glossario/regex/"
markdown_url: "https://python.dev.br/glossario/regex.MD"
description: "Domine expressoes regulares em Python com o modulo re: padroes, metacaracteres, grupos, substituicao e boas praticas para validacao e busca de texto."
date: "2025-10-08"
author: ""
---

# 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

```python
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

```python
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

```python
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

```python
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.

```python
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

```python
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.
