A maioria das falhas de expressões regulares não são erros de sintaxe. Um padrão pode ser perfeitamente válido e ainda assim estar errado: casa demais, casa de menos ou — pior — trava a página quando encontra uma string hostil. Entre um padrão que funciona nos exemplos da sua cabeça e um que funciona em dados reais, está o teste.
Este artigo descreve um fluxo de trabalho prático para escrever, testar e depurar expressões regulares no navegador, além dos modos de falha que mordem com mais frequência.
Teste com dados reais, não com exemplos de brinquedo
Strings de brinquedo puxam o padrão para o lado errado. A entrada real traz quebras de linha esquecidas, espaços finais, emoji, valores vazios e quarenta quilobytes de markup copiado.
- Cole a pior amostra real que você tiver — idealmente a que já quebrou alguma coisa.
- Inclua a string vazia, um único caractere e uma linha muito longa.
- Inclua texto não ASCII se a entrada puder contê-lo:
Ü,日本語,🙂. - Conte as correspondências, não só a primeira. Quantificadores com off-by-one e sobreposição gulosa só aparecem aqui.
Testar com realce ao vivo torna isso barato: cada posição de correspondência se atualiza enquanto você edita o padrão, em vez de ressurgir três dias depois num arquivo de log.
Flags mudam o significado de um padrão
A mesma expressão se comporta de forma diferente conforme as flags com que roda:
| Flag | Efeito | Surpresa típica |
|---|---|---|
i |
ignora maiúsculas e minúsculas | também casa identificadores que você queria distinguir |
g |
global — encontra todas as correspondências | em JavaScript, test() e exec() mantêm estado entre chamadas |
m |
multilinha — ^ e $ por linha |
^ deixa de significar “início da string” |
s |
O ponto também casa quebras de linha | .* começa a cruzar fronteiras de linha |
u |
modo Unicode | indispensável para escapes por ponto de código |
A flag g do JavaScript merece menção: com ela, regex.test() avança lastIndex, então chamadas repetidas ao mesmo objeto retornam respostas diferentes. É a fonte clássica do bug “funciona uma vez e falha na segunda tentativa”.
Grupos de captura e grupos nomeados
Grupos extraem dados, mas também custam memória e deixam o padrão mais difícil de ler.
// grupos nomeados sobrevivem à reordenação; os numerados, não
const re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const m = "2026-09-22".match(re);
m.groups.year; // "2026"
m.groups.month; // "09"
Prefira grupos nomeados aos numerados, para que reordenar o padrão não desloque silenciosamente suas referências. Se você precisa de parênteses só para agrupar e não para capturar, use um grupo sem captura: (?:...).
Backtracking catastrófico
Quantificadores aninhados como (a+)+$ ou (\s*)* podem levar um motor a tempo exponencial em strings que quase casam. O padrão é instantâneo em entrada amigável e trava em uma hostil — e é exatamente a hostil que um atacante envia.
- Evite quantificadores sobre grupos que já contêm quantificadores.
- Ancore quando puder.
^e$permitem que o motor rejeite cedo. - Estresse com uma string longa de quase-correspondência. Se o tempo de match sobe muito conforme caracteres são adicionados, o padrão não é seguro.
- Considere um motor de tempo linear (estilo RE2) para entrada não confiável num servidor.
Deixe os padrões legíveis
- Nomeie o padrão no código —
const ISO_DATE = /.../ganha de um literal anônimo repetido em seis arquivos. - Use o modo de espaçamento livre (
x) quando o motor suportar, para adicionar comentários e espaços dentro do padrão. - Seja explícito sobre dígitos.
[0-9]significa dígitos ASCII;\dtambém casa outros sistemas de escrita no modo Unicode. - Deixe dois exemplos com o padrão: um que deve casar e outro que não deve.
Um fluxo de trabalho prático
| Etapa | O que você verifica |
|---|---|
| 1. Escreva o padrão menor que casa com uma amostra real | o realce cai onde você espera |
| 2. Adicione amostras negativas | sem correspondências em entradas que devem falhar |
| 3. Ative as flags deliberadamente | cada flag está ali por um motivo |
| 4. Estresse com entradas longas e hostis | a correspondência aparece na hora |
| 5. Converta para código com grupos nomeados | nenhuma referência posicional sobrando |
Experimente
Abra um testador de regex, cole seu padrão e uma amostra real e veja cada correspondência ganhar realce enquanto você digita. Como o teste roda no navegador, o texto que você está validando nunca sai do seu dispositivo — e isso importa assim que a amostra contém um token, uma chave ou dados de clientes.