Expressões regulares do zero: um guia prático para iniciantes
O que é uma regex e onde ela vive, os metacaracteres essenciais, grupos e capturas, padrões prontos e os erros que tornam a regex lenta.
Atualizado em 30 de junho de 2026 · 9 min de leitura
O que é uma regex e onde ela vive
Uma expressão regular (ou regex) é uma pequena linguagem para descrever padrões de texto. Em vez de procurar a palavra exata "gato", você descreve uma regra — "três dígitos, um traço, mais quatro dígitos" — e o motor de regex encontra tudo que se encaixa. É a diferença entre apontar para uma coisa e descrever uma família inteira de coisas.
Você já cruzou com regex sem saber. Ela está no "Localizar e substituir" avançado do VS Code, no comando grep do terminal, na validação daquele formulário que reclamou do seu e-mail, e em praticamente toda linguagem de programação: JavaScript, Python, PHP, Java, Go. A sintaxe é quase a mesma em todas porque a maioria descende do mesmo avô, o Perl (daí o nome PCRE, Perl Compatible Regular Expressions).
Na prática, uma regex faz três coisas: testar se um texto bate com o padrão (verdadeiro ou falso), extrair os pedaços que interessam e substituir o que casou por outra coisa. O melhor jeito de aprender é experimentando: cole um padrão e um texto no Testador de Regex e veja, em tempo real, o que acende e o que não acende.
Os metacaracteres essenciais
A maior parte dos caracteres em uma regex representa a si mesma: o padrão casa casa com a palavra "casa". A mágica vem dos metacaracteres, símbolos com significado especial. Estes são os que você usa 90% do tempo:
| Símbolo | Significa | Exemplo |
|---|---|---|
| . | qualquer caractere (menos quebra de linha) | c.sa → casa, cosa, c8sa |
| \d | um dígito de 0 a 9 | \d\d → 42 |
| \w | letra, dígito ou _ (sem acento!) | \w+ → palavra1 |
| \s | espaço, tab ou quebra de linha | a\sb → "a b" |
| \D \W \S | o oposto de cada um acima | \D → não-dígito |
Um detalhe que pega todo brasileiro: \w equivale a [A-Za-z0-9_] e não inclui letras acentuadas. Em "João", o "ã" não é considerado \w. Para capturar palavras em português, ou você lista os acentos à mão ([A-Za-zÀ-ÿ]) ou usa o modo Unicode com propriedades, como \p{L} e a flag u.
Quando você precisa do significado literal de um metacaractere, coloque uma barra invertida na frente. Para casar um ponto de verdade — em "arquivo.pdf" —, escreva \., não . (que casaria com qualquer caractere).
Classes, quantificadores e âncoras
Classes de caracteres
Os colchetes criam um conjunto: case com qualquer um dos caracteres dentro deles. [aeiou] casa uma vogal; [a-z] usa um intervalo; [0-9A-F] casa um dígito hexadecimal. Um circunflexo logo após o colchete inverte tudo: [^0-9] casa qualquer coisa que não seja dígito.
Quantificadores
Sozinho, um padrão casa uma ocorrência. Os quantificadores dizem quantas vezes repetir o que vem antes:
?— zero ou uma vez (opcional)*— zero ou mais vezes+— uma ou mais vezes{3}— exatamente 3;{2,4}— de 2 a 4;{2,}— 2 ou mais
Então \d{5}-?\d{3} lê "cinco dígitos, um traço opcional, três dígitos". Por padrão os quantificadores são gananciosos (greedy): pegam o máximo que conseguem. Em <b>oi</b>, o padrão <.*> casa a linha inteira, não só a primeira tag. Acrescentar um ? torna o quantificador preguiçoso (lazy): <.*?> para na primeira ocorrência possível.
Âncoras
Âncoras não casam caracteres — casam posições. O ^ marca o início do texto e o $ marca o fim. Eles são o que separa "validar" de "encontrar". Sem âncoras, \d{3} aceita "abc123def" porque existe uma sequência de três dígitos lá dentro. Com ^\d{3}$, o texto inteiro precisa ser exatamente três dígitos. O \b marca uma fronteira de palavra, útil para casar a palavra isolada e não como parte de outra.
Grupos e capturas
Os parênteses fazem duas coisas ao mesmo tempo: agrupam um trecho para aplicar um quantificador a ele e capturam o que casou para você reaproveitar depois. Em (ha)+, o + repete o grupo inteiro, casando "ha", "haha", "hahaha".
O uso clássico é extrair pedaços. Tome o padrão (\d{2})/(\d{2})/(\d{4}) aplicado a "30/06/2026". Ele cria três grupos: o grupo 1 vira "30", o 2 vira "06" e o 3 vira "2026". Numa substituição, você se refere a eles por $1, $2, $3. Substituir por $3-$2-$1 transforma a data brasileira "30/06/2026" no formato ISO "2026-06-30" em uma linha.
Variações úteis: (?:...) agrupa sem capturar (mais rápido e mantém a numeração limpa quando você só precisa do quantificador); (?<ano>\d{4}) dá um nome ao grupo, e você o acessa por ano em vez de contar parênteses; e a barra vertical | é o "ou": (jpg|png|gif) casa qualquer uma das três extensões.
Padrões prontos: e-mail, CEP e telefone
Com o vocabulário acima, dá para montar os padrões que mais aparecem no dia a dia. Use o Testador de Regex para colar cada um e ver casando.
| O quê | Padrão | Casa |
|---|---|---|
| CEP | ^\d{5}-?\d{3}$ | 01310-100 / 01310100 |
| Telefone com DDD | ^\(\d{2}\)\s?9?\d{4}-?\d{4}$ | (11) 98765-4321 |
| E-mail (pragmático) | ^[^\s@]+@[^\s@]+\.[^\s@]+$ | [email protected] |
Repare no padrão de e-mail. Ele não tenta listar todos os domínios do mundo; só exige "algo, um arroba, algo, um ponto, algo", sem espaços. Tentativas de criar a regex "perfeita" de e-mail produzem monstros de centenas de caracteres que ainda assim erram casos válidos. Para a maioria dos formulários, o padrão simples acima já filtra os erros de digitação grosseiros — e a validação de verdade é mandar um e-mail de confirmação. Se quiser uma checagem mais robusta sem montar a regex à mão, o Validador de Email faz esse trabalho.
Regex também serve para limpar texto, não só validar. Para gerar um slug de URL a partir de um título, o passo central é substituir tudo que não for letra ou número por um hífen: [^a-z0-9]+ → - (depois de remover acentos e baixar a caixa). É exatamente isso que o Slugify faz: "Olá, Mundo!" vira "ola-mundo".
Erros que travam ou tornam a regex lenta (backtracking)
Regex é poderosa, mas tem armadilhas. Quatro causam quase toda dor de cabeça:
- Esquecer de escapar o ponto. Validar "site.com" com
site.comaceita também "siteXcom", porque o.casa qualquer caractere. Usesite\.com. - Validar sem âncoras. Sem
^e$, "12345abc" passa numa regra que deveria aceitar só "12345". - Ser ganancioso demais.
.*costuma engolir mais do que você queria; troque por uma versão preguiçosa.*?ou por uma classe específica. - Backtracking catastrófico. O erro mais perigoso, porque pode congelar o programa.
O backtracking acontece quando o motor precisa testar muitas combinações para decidir se algo casa. Quantificadores aninhados são a receita do desastre. Veja ^(\d+)+$ aplicado a uma string longa de dígitos terminada por uma letra, como "99999999999999999999X". Como o "X" nunca vai casar com $, o motor tenta repartir os dígitos entre o + de dentro e o de fora de todas as maneiras possíveis antes de desistir — um número exponencial de tentativas. Com 25 dígitos, isso já pode levar segundos; com 40, trava. A correção é simples: ^\d+$ faz o mesmo trabalho sem aninhar.
Esse problema tem até nome de segurança: ReDoS (Regular expression Denial of Service). Uma regex mal construída em um servidor pode ser derrubada por um único texto malicioso. A defesa é evitar quantificadores aninhados ((a+)+, (.*)*), preferir classes específicas a .* e sempre testar com entradas longas no Testador de Regex antes de subir para produção.
Perguntas frequentes
A regex é igual em todas as linguagens?
Quase. O núcleo — metacaracteres, quantificadores, grupos — é o mesmo em JavaScript, Python, PHP, Java e na maioria das ferramentas. As diferenças aparecem nos recursos avançados: o JavaScript ganhou lookbehind e grupos nomeados só em 2018, e não tem quantificadores possessivos nem grupos atômicos como o PCRE. Para padrões do dia a dia, o que você aprende aqui vale em todo lugar.
Como faço uma busca ignorando maiúsculas e minúsculas?
Use a flag i (de insensitive). Em JavaScript, /casa/i casa "Casa", "CASA" e "casa". Outras flags úteis: g (encontrar todas as ocorrências, não só a primeira) e m (faz ^ e $ valerem por linha).
Posso usar regex para validar e-mail de forma definitiva?
Não existe regex que aceite exatamente todos os e-mails válidos e rejeite todos os inválidos — a especificação é cheia de exceções. Use um padrão simples para barrar erros óbvios de digitação e confirme o endereço de verdade enviando uma mensagem. A validação por regex é o porteiro, não a prova final.
Dá para analisar HTML com regex?
Para tarefas pontuais (achar todos os href, por exemplo), funciona. Para realmente entender a estrutura de um documento, não: HTML pode aninhar de formas que uma regex não consegue acompanhar. Aí o caminho é um parser de verdade. Regex brilha em texto "plano" com padrões locais; documentos com hierarquia pedem outra ferramenta.
Qual a diferença entre greedy e lazy?
Greedy (padrão) pega o máximo de caracteres possível e depois "devolve" se precisar; lazy (com ? depois do quantificador) pega o mínimo e só estende se for obrigada. Em "<a><b>", <.*> casa tudo, enquanto <.*?> casa só "<a>". Escolher o certo evita capturar texto demais.
Ferramentas citadas neste guia
Testador de Regex
Teste expressões regulares em tempo real. Veja os matches destacados e os grupos capturados.
Validador de Email
Verifique se um endereço de email é válido. Analisa a estrutura, domínio e parte local. Processado no navegador, sem enviar o email para nenhum servidor.
Slugify
Converta títulos e textos em slugs amigáveis para URLs. Remove acentos, converte para minúsculas e substitui espaços por hífens. Essencial para SEO.
Continue lendo
JSON na prática: formatar, validar e converter sem dor de cabeça
A sintaxe do JSON em cinco minutos, os erros mais comuns, formatar vs minificar e como converter para CSV, YAML e XML.
7 min de leitura
JWT por dentro: a anatomia de um token
As três partes de um JWT, o que vai (e o que nunca deve ir) no payload, como a assinatura protege o token e por que decodificar não é confiar.
7 min de leitura