Validação de formulário
Celular, CEP, formato de data e força de senha — os três padrões dos níveis 22–24 podem ir direto para um formulário de front-end; lembre-se das âncoras e deixe checagens semânticas como "30 de fevereiro" para o código.
Guide
O curso de expressões regulares é um tutorial interativo de 25 níveis: cada nível traz um texto de teste e um objetivo ("casar estes trechos e não casar aqueles" ou "capturar uma parte específica"), você altera a expressão no campo de entrada e todas as correspondências e grupos são destacados ao vivo à direita, enquanto o verificador diz item por item o que já foi atingido. Toda a verificação roda no motor de expressões regulares do próprio JavaScript do navegador e nenhum texto é enviado.
Atualizado em 2026-09-094 sources14 min read
O curso de expressões regulares é um tutorial interativo de 25 níveis: cada nível traz um texto de teste e um objetivo ("casar estes trechos e não casar aqueles" ou "capturar uma parte específica"), você altera a expressão no campo de entrada e todas as correspondências e grupos são destacados ao vivo à direita, enquanto o verificador diz item por item o que já foi atingido. Toda a verificação roda no motor de expressões regulares do próprio JavaScript do navegador e nenhum texto é enviado.
O curso avança por dificuldade: começa com literal, ponto e escape, o básico de "achar caracteres"; depois vêm classes e intervalos de caracteres, as classes predefinidas \d \w \s e os quatro quantificadores; em seguida âncoras e fronteira de palavra, alternância, os três tipos de grupo com retrorreferência, ganância e preguiça; depois as asserções de lookahead e lookbehind e as flags; e no fim três padrões reais (celular da China continental, e-mail e data) para praticar tudo junto, fechando com um nível de "backtracking catastrófico" em que você mesmo escreve uma expressão que trava o motor e depois a conserta.
Leva cerca de 60 minutos. Serve para quem nunca escreveu uma expressão regular ou para quem "sabe copiar mas não sabe alterar"; quem já domina o assunto pode ir direto para a parte de lookaround e armadilhas, a partir do nível 17.
?lesson=n que abre direto naquele nível. "Redefinir progresso" apaga todos os registros do curso.O curso em si está acima desta página: escolha o nível no índice à esquerda, digite a expressão no meio e o veredito aparece na hora.
O objetivo do nível 14, "grupos de captura", é extrair o ano de 2026-09-09. Veja o registro de uma conclusão:
Texto de teste Publicado em: 2026-09-09, prazo: 2027-01-31
Primeira tentativa \d+
correspondências 2026 09 09 2027 01 31 ← 6 correspondências, sem grupo de captura
veredito ✕ deveria casar só duas datas completas ✕ o grupo 1 deveria ser o ano
Segunda tentativa (\d{4})-\d{2}-\d{2}
correspondências 2026-09-09 2027-01-31 ← 2 correspondências
grupo 1 2026 2027
veredito ✓ 2 correspondências ✓ grupo 1 = 2026 / 2027 → concluído
O nível 25, "backtracking catastrófico", funciona ao contrário: primeiro você escreve um padrão de quantificadores aninhados como ^(a+)+$ e testa com uma sequência de aaaaaaaaaaaaaaaaaaaaaaaaaaaa!, e a página informa que o número de tentativas cresce de forma exponencial; depois é preciso trocar por uma forma equivalente, como ^a+$, para concluir.
Uma expressão regular (regular expression) descreve "como é uma classe de strings" com um pequeno conjunto de símbolos. Letras e números em geral representam a si mesmos, e cerca de uma dúzia de metacaracteres (. * + ? ^ $ | ( ) [ ] { } \) tem significado especial. O motor percorre o texto da esquerda para a direita com o padrão, tenta casar em cada posição e, quando encontra, informa posição e comprimento. Este curso usa o dialeto do JavaScript (ECMAScript), que é quase igual ao de Python, Java e Go na sintaxe básica, com diferenças concentradas em lookaround, propriedades Unicode e algumas flags.
cat casa os três caracteres c, a e t em sequência. O ponto . casa qualquer caractere, exceto quebra de linha, então c.t casa cat, cut e c9t. Quando você quer mesmo encontrar um ponto — o que precede a extensão de um arquivo, por exemplo — escreva \.: a barra invertida devolve ao metacaractere o sentido literal. Todos os metacaracteres podem ser escapados assim; dentro de uma classe de caracteres, só ] \ ^ - precisam de escape.
Os colchetes listam caracteres candidatos: [aeiou] casa qualquer vogal; [a-z] e [0-9] usam o hífen para indicar intervalo e podem ser combinados como [A-Za-z0-9_]; um ^ no começo inverte, e [^0-9] casa qualquer coisa que não seja dígito. As três classes predefinidas mais usadas são abreviações disso:
| Classe | Equivale a | Observação |
|---|---|---|
\d |
[0-9] |
dígito (não inclui numerais chineses nem dígitos de largura total) |
\w |
[A-Za-z0-9_] |
"caractere de palavra"; ideogramas chineses não contam |
\s |
[ \t\n\r\f\v…] |
espaço em branco, incluindo o espaço de largura total |
As versões maiúsculas \D \W \S são as negações de cada uma. O \w não incluir ideogramas chineses é a armadilha mais comum: para casar caracteres chineses é preciso escrever [\u4e00-\u9fa5] ou usar \p{Script=Han} com a flag u.
O quantificador vem depois de um átomo (um caractere, uma classe ou um grupo) e define quantas vezes ele se repete:
* zero ou mais vezes, + uma ou mais vezes, ? zero ou uma vez;{n} exatamente n vezes, {n,} pelo menos n vezes, {n,m} de n a m vezes.\d{4} é mais legível que \d\d\d\d, e \d{11} é a quantidade de dígitos de um celular. O quantificador afeta apenas o átomo imediatamente à sua esquerda: ab+ é um a seguido de um ou mais b, e para repetir o ab inteiro é preciso escrever (ab)+.
^ e $ não casam caracteres, e sim posições: o início e o fim da string (em modo multilinha, de cada linha). Validação de formulário quase sempre pede ^…$, senão \d{11} "casa" os 11 primeiros dígitos de um número de 12. O \b é a fronteira de palavra — a posição entre \w e \W (ou entre eles e o início e o fim da string). \bcat\b casa a cat, mas não concatenate. E como o \w não inclui ideogramas chineses, o \b é praticamente inútil em texto chinês.
O | significa "ou" e tem a precedência mais baixa: cat|dog casa uma das duas palavras; para limitar o alcance, use parênteses, como em gr(a|e)y. Os parênteses também criam um grupo de captura: depois de casar, dá para pegar o texto do grupo pelo número (match[1]) ou referenciá-lo na substituição com $1 — um dos usos mais produtivos das expressões regulares, como trocar 2026-09-09 por 09/09/2026 com um único replace.
(?<year>\d{4}) é um grupo nomeado, lido por groups.year, que erra menos que a numeração quando o padrão muda. (?:…) é o grupo sem captura: agrupa sem ocupar numeração, ideal quando você só quer delimitar o alcance de um quantificador ou de uma alternância. E \1 é a retrorreferência — exige que aqui apareça de novo o conteúdo capturado pelo grupo 1: (\w)\1 casa letras dobradas como ll e oo, e <(\w+)>.*?</\1> casa tags HTML em par.
Por padrão o quantificador é ganancioso: come o máximo possível e devolve o que sobrou. Em "a" and "b", o padrão ".+" casa de uma vez tudo o que vai da primeira à última aspa. Acrescentar ? ao quantificador o torna preguiçoso: ".+?" come o mínimo e produz duas correspondências, "a" e "b". Uma forma mais precisa é usar a classe negada "[^"]+", que não depende de backtracking e costuma ser mais rápida.
O lookaround casa apenas posições, como uma âncora, mas com a condição "existe ou não um padrão ao lado":
(?=…) lookahead: depois precisa vir …; \d+(?=px) casa o 100 de 100px sem incluir a unidade no resultado.(?!…) lookahead negativo: depois não pode vir ….(?<=…) lookbehind: antes precisa haver …; (?<=¥)\d+ casa o número do preço sem o símbolo da moeda.(?<!…) lookbehind negativo.O JavaScript suporta lookbehind desde o ES2018, mas só ficou disponível em todos os casos a partir do Safari 16.4; já o lookbehind do Python exige comprimento fixo. Validar força de senha é o uso típico de lookaround: ^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}$ usa três lookaheads para verificar, da mesma posição, "tem dígito, tem minúscula, tem maiúscula" e depois .{8,} consome a string inteira.
As flags ficam fora do padrão: i ignora maiúsculas e minúsculas; g busca todas as correspondências em vez da primeira (o destaque do curso usa g o tempo todo); m faz ^ $ casarem em cada linha; s permite que . case também quebras de linha; u ativa o modo Unicode, em que . casa por ponto de código e não por unidade UTF-16, e um emoji passa a contar como um caractere; y é a correspondência pegajosa, que precisa acontecer exatamente em lastIndex.
Celular da China continental: ^1[3-9]\d{9}$ — começa com 1, o segundo dígito vai de 3 a 9 e são 11 no total. Não tente enumerar as faixas das operadoras: elas aumentam todo ano.
E-mail: uma expressão que siga a RFC 5322 ao pé da letra passa de milhares de caracteres e não é nada prática. O razoável em um formulário é ^[^\s@]+@[^\s@]+\.[^\s@]+$: um único @, os dois lados não vazios e pelo menos um ponto na parte do domínio. A validação de verdade é enviar um e-mail de confirmação.
Data: ^(\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$ limita o mês a 01–12 e o dia a 01–31, mas não sabe quantos dias tem fevereiro — validação de sintaxe fica com a expressão regular e validação de semântica fica com o código.
Os motores de expressão regular de JavaScript, Python, Java e PCRE são de backtracking: diante de várias formas de dividir a string, tentam uma e, se falhar, voltam e tentam a seguinte. Quantificadores aninhados fazem o número de divisões crescer exponencialmente: ^(a+)+$ diante de 30 letras a e um ! obriga o motor a testar mais de 2^30 divisões antes de declarar a falha, e a aba do navegador trava por segundos ou minutos. Se um padrão assim aceita entrada do usuário, ele é um ataque de negação de serviço (ReDoS).
Os princípios para evitar: não deixar dois quantificadores vizinhos casarem os mesmos caracteres ((a+)+, (\w+\s?)+ e (.*)* são sinais de perigo); trocar o preguiçoso .*? por uma classe negada; e impor um limite de comprimento à entrada. As bibliotecas de Go e Rust usam implementações Thompson NFA / DFA, que garantem tempo linear, mas em troca não suportam retrorreferência nem lookaround — o artigo de Russ Cox é a melhor explicação da diferença entre as duas abordagens.
Casar estruturas aninhadas (parênteses em par, um HTML inteiro), tarefas que exigem "contar" (verificar se os parênteses abrem e fecham na mesma quantidade) e decisões que dependem de contexto semântico (se aquele número é uma data válida): nada disso a expressão regular faz, ou faz muito mal. Ela é uma ferramenta da camada lexical: achar tokens, dividir, validar o simples e substituir em lote — nisso ela é insubstituível.
(?i) do PCRE, o (?P<name>) do Python e o \p{javaLowerCase} do Java não entram, nem as classes POSIX [[:alpha:]].u é apresentada rapidamente no nível de flags; os escapes de propriedade \p{…} e as operações de conjunto da flag v ficam fora do curso.\w casa ideogramas chineses": não. O \w só tem letras ASCII, dígitos e sublinhado; para casar caracteres chineses use [\u4e00-\u9fa5] ou \p{Script=Han} (com a flag u).. casa qualquer caractere": por padrão ele não casa quebra de linha; para atravessar linhas, adicione a flag s ou use [\s\S].\d{11}, só passa número de 11 dígitos": sem âncoras, o padrão encontra 11 dígitos dentro de um número maior; validação exige ^…$.[A-z] são todas as letras": no ASCII, entre o Z maiúsculo (90) e o a minúsculo (97) existem seis símbolos, [ \ ] ^ _ \``, que entram junto; escreva [A-Za-z]`.ab+ repete só o b; ab{2} casa abb e não casa abab.> dentro de atributos e comentários quebram o padrão, então use um interpretador de DOM.Celular, CEP, formato de data e força de senha — os três padrões dos níveis 22–24 podem ir direto para um formulário de front-end; lembre-se das âncoras e deixe checagens semânticas como "30 de fevereiro" para o código.
A busca e substituição do VS Code, do Sublime e das IDEs da JetBrains aceita expressões regulares e a referência $1. Depois da parte de grupos, você troca todos os 2026-09-09 por 09/09/2026 de uma vez ou prefixa todos os console.log(.
Para tirar IP, código de status e tempo de dezenas de milhares de linhas de log, padrões como (\d+\.\d+\.\d+\.\d+).*?" (\d{3}) (\d+)ms combinados com grupos nomeados dão a estatística em poucas linhas de script.
Ao ver (\w+\s?)+$, (.*a)+ ou (a|aa)+ em um ponto que trata entrada do usuário, peça a reescrita ou a imposição de um limite de comprimento.
A verificação olha o resultado, não a forma: basta que tudo o que deve casar case, nada do que não deve casar e os grupos de captura confiram. A resposta de referência é apenas uma das formas possíveis.
Normalmente é um trecho que não deveria casar e casou, ou um resultado que pegou um caractere a mais que o alvo (pontuação junto, por exemplo). Veja qual item da barra de resultado está com ✕.
A sintaxe dos níveis 1–18 é totalmente comum às linguagens mais usadas. O lookbehind do nível de lookaround exige comprimento fixo em Python, e o grupo nomeado em Python é escrito (?P<name>…); as flags variam de linguagem para linguagem.
Fica no localStorage do navegador atual e não é enviado. Trocar de navegador ou limpar os dados do site apaga; anote em que nível você está com o link de "compartilhar este nível".
A demonstração usa uma contagem simulada de passos e considera "backtracking catastrófico" quando passa do limite. Executar de verdade deixaria a aba sem resposta e não daria retorno nenhum.
O curso roda inteiramente no navegador: a expressão e o texto de teste que você digita vão apenas para o motor de expressões regulares do próprio navegador, sem envio a servidor nenhum; o progresso fica no localStorage do seu aparelho. Ao fechar a página, o que foi digitado é liberado.
Atualizado em 2026-09-09
Tutorial interativo de 25 níveis: literais, classes de caracteres, quantificadores, grupos, lookarounds e armadilhas de backtracking, com correspondências ao vivo
Esta ferramenta ainda não está totalmente traduzida; parte do conteúdo usa o idioma de origem ou um idioma de reserva.
ObjetivoEscreva uma expressão que corresponda a cada palavra que contenha cat e nada mais.
O regex mais simples é uma série de caracteres comuns: cat pesquisa no texto por c, a, t consecutivos. Por padrão, uma regex significa "contém", não "igual" - concat e category contêm cat, portanto, eles também correspondem. Letras, dígitos, espaços e caracteres CJK são todos literais; apenas cerca de uma dúzia de símbolos são especiais, e as próximas lições os abordam um por um.