icardb
Expressões regulares na prática: guia com exemplos em JavaScript e Python
Voltar para artigosPROGRAMAÇÃO

Expressões regulares na prática: guia com exemplos em JavaScript e Python

Por Redação icardb Publicado em 7 min de leitura

Uma expressão regular (regex) é um padrão que descreve um conjunto de textos: "quatro dígitos, um hífen, dois dígitos" é uma forma de descrever datas no formato 2026-10. Com ela, dá para validar formatos, encontrar trechos e fazer substituições em massa com uma linha de código. A sintaxe parece hostil no começo, mas o núcleo usado no dia a dia cabe em uma tabela. Os exemplos abaixo podem ser colados no console do navegador ou no interpretador Python.

Quando usar — e quando não usar

Regex brilha em textos com formato previsível: validar CEP ou placa, extrair campos de linhas de log, renomear padrões em vários arquivos, limpar espaços duplicados. Ela é a ferramenta errada para estruturas aninhadas, como HTML, JSON ou código-fonte: para isso existem parsers, que entendem a hierarquia do documento.

Também vale desconfiar de expressões que tentam validar tudo. O formato de endereços de e-mail definido nas RFCs é tão amplo que uma regex completa fica ilegível; na prática, uma checagem simples (algo@algo.algo) seguida de um e-mail de confirmação é mais confiável.

A sintaxe essencial em uma tabela

SímboloSignificadoExemploCasa com
.Qualquer caractere, exceto quebra de linhaa.cabc, a-c, a7c
\dUm dígito\d{3}123
\wLetra, dígito ou _ (em JavaScript, só letras sem acento)\w+nome_1
\sEspaço, tabulação ou quebra de linhaa\sba b
[abc] / [^abc]Um dos caracteres / nenhum deles[aeiou]uma vogal
^ e $Início e fim do texto (ou da linha, com a flag m)^oi$exatamente "oi"
* + ?Zero ou mais / um ou mais / zero ou umcolou?rcolor, colour
{n,m}Entre n e m repetições\d{2,4}12, 123, 1234
( )Grupo de captura(\d{4})-(\d{2})captura ano e mês
(?: )Grupo sem captura(?:ab)+abab
(?<nome> )Grupo nomeado (em Python: (?P<nome> ))(?<ano>\d{4})ano
|Alternativagato|cãogato ou cão
\bFronteira de palavra\bsol\bsol, mas não solar

Uma diferença que pega muita gente: em JavaScript, \w e \b consideram apenas letras ASCII, então "ação" não é uma palavra inteira para eles. Em Python 3, com textos str, \w reconhece letras acentuadas. Para textos em português no JavaScript, use classes explícitas como [A-Za-zÀ-ÿ] ou a flag u com \p{L}.

Exemplos em JavaScript

javascript
// 1. Extrair uma data AAAA-MM-DD com grupos nomeados
const re = /(?<ano>\d{4})-(?<mes>\d{2})-(?<dia>\d{2})/;
const m = "Publicado em 2026-10-29".match(re);
console.log(m.groups.dia, m.groups.mes, m.groups.ano); // 29 10 2026

// 2. Reformatar todas as datas para DD/MM/AAAA (flag g = global)
const texto = "Início 2026-01-05, fim 2026-03-20";
console.log(texto.replace(/(\d{4})-(\d{2})-(\d{2})/g, "$3/$2/$1"));
// "Início 05/01/2026, fim 20/03/2026"

// 3. Percorrer linhas de log com matchAll (exige a flag g; m faz ^ e $ valerem por linha)
const log = "GET /api 200\nPOST /login 401\nGET /home 200";
for (const [, metodo, rota, status] of log.matchAll(/^(\w+) (\S+) (\d{3})$/gm)) {
  if (status !== "200") console.log(metodo, rota, status); // POST /login 401
}

// 4. CEP: 5 dígitos, hífen opcional, 3 dígitos — ^ e $ impedem sobras
const cep = /^\d{5}-?\d{3}$/;
console.log(cep.test("01310-100"), cep.test("01310100"), cep.test("0131-0100"));
// true true false

// 5. Letras com acento: \p{L} com a flag u
console.log("ação rápida".match(/\p{L}+/gu)); // ["ação", "rápida"]

Cuidado com regex que tem a flag g e é reutilizada com test(): ela guarda a posição da última busca em lastIndex, e a chamada seguinte começa dali — um resultado alternando entre true e false costuma ser isso. Para validação, não use g.

Os mesmos exemplos em Python

python
import re

# Grupos nomeados usam a sintaxe (?P<nome>...)
m = re.search(r"(?P<ano>\d{4})-(?P<mes>\d{2})-(?P<dia>\d{2})", "Publicado em 2026-10-29")
print(m["dia"], m["mes"], m["ano"])  # 29 10 2026

# Substituição com referência aos grupos: \3/\2/\1
texto = "Início 2026-01-05, fim 2026-03-20"
print(re.sub(r"(\d{4})-(\d{2})-(\d{2})", r"\3/\2/\1", texto))
# Início 05/01/2026, fim 20/03/2026

# Compile quando o padrão for reutilizado
LINHA = re.compile(r"^(\w+) (\S+) (\d{3})$", re.MULTILINE)
log = "GET /api 200\nPOST /login 401\nGET /home 200"
for metodo, rota, status in LINHA.findall(log):
    if status != "200":
        print(metodo, rota, status)  # POST /login 401

# fullmatch exige que o texto inteiro case, sem precisar de ^ e $
print(bool(re.fullmatch(r"\d{5}-?\d{3}", "01310-100")))  # True

Em Python, escreva padrões sempre como raw strings (r"..."). Sem o r, "\b" vira o caractere de backspace antes mesmo de chegar ao módulo re, e a expressão para de funcionar sem nenhum erro aparente.

Ganancioso versus preguiçoso

Por padrão, os quantificadores * e + são gananciosos: casam o máximo possível. Acrescentar ? depois deles os torna preguiçosos, casando o mínimo. A diferença aparece logo em textos com delimitadores repetidos:

javascript
const html = "<b>negrito</b> e <i>itálico</i>";
console.log(html.match(/<.+>/)[0]);   // "<b>negrito</b> e <i>itálico</i>" (ganancioso)
console.log(html.match(/<.+?>/)[0]);  // "<b>" (preguiçoso)
console.log(html.match(/<[^>]+>/g));  // ["<b>", "</b>", "<i>", "</i>"]

A terceira forma — uma classe negada, [^>]+ — costuma ser a melhor: diz exatamente o que pode aparecer entre os delimitadores e evita retrocessos desnecessários do motor de busca.

Desempenho e segurança: o risco de ReDoS

Os motores de regex de JavaScript, Python, Java e PCRE usam retrocesso (backtracking): quando um caminho falha, voltam e tentam outro. Com quantificadores aninhados, como em ^(a+)+$, uma entrada que quase casa — muitos "a" seguidos de um "!" — obriga o motor a testar um número de combinações que cresce exponencialmente. Uma única requisição com esse texto pode travar um servidor Node.js, já que o event loop fica preso. Esse ataque é chamado de ReDoS (Regular expression Denial of Service).

  • Evite quantificadores aninhados e alternativas que se sobrepõem, como (a|a)+ ou (\w+\s?)+.
  • Limite o tamanho da entrada antes de aplicar a regex em dados vindos do usuário.
  • Prefira classes específicas ([^,]+) a curingas genéricos (.*) dentro de repetições.
  • Para padrões vindos de usuários, use um motor de tempo linear: o pacote regexp da biblioteca padrão de Go e a biblioteca RE2 (com bindings para Node.js e Python) garantem tempo proporcional ao tamanho da entrada, em troca de não suportar alguns recursos como retrovisores.

Como testar e manter expressões regulares

Sites como o regex101 mostram, passo a passo, o que cada parte do padrão está casando e permitem escolher o dialeto (JavaScript, Python, PCRE). Mas o teste que conta é o automatizado: para cada regex importante, escreva casos que devem casar e casos que não devem — inclusive os de borda, como string vazia e espaços nas pontas. Em Python, a flag re.VERBOSE permite quebrar o padrão em várias linhas com comentários, o que ajuda muito quem for mantê-lo depois.

Conclusão

Comece pelo núcleo — classes (\d, \s, colchetes), quantificadores, âncoras e grupos — e pratique em problemas reais, como extrair dados de um log. Use âncoras em validações, raw strings em Python, cuidado com a flag g em JavaScript e desconfiança com quantificadores aninhados. E quando o texto tiver estrutura aninhada, troque a regex por um parser.

Perguntas frequentes

+Regex é igual em todas as linguagens?

O núcleo (classes, quantificadores, âncoras, grupos) é praticamente o mesmo. Mudam detalhes: a sintaxe de grupos nomeados ((?<nome>) em JavaScript, (?P<nome>) em Python), o suporte a Unicode em \w e recursos avançados como lookbehind e retrovisores. Ferramentas como o regex101 permitem testar no dialeto certo.

+Como validar e-mail com regex?

Use uma checagem simples, como ^[^\s@]+@[^\s@]+\.[^\s@]+$, apenas para pegar erros de digitação óbvios, e confirme o endereço enviando um e-mail. Regex nenhuma garante que o endereço existe ou pertence à pessoa.

+Qual a diferença entre test, match e matchAll no JavaScript?

test() devolve apenas true ou false. match() sem a flag g devolve a primeira ocorrência com os grupos; com g, devolve só os textos encontrados, sem grupos. matchAll() exige a flag g e devolve todas as ocorrências com seus grupos, o que costuma ser o mais útil para extração.

+Expressões regulares deixam o código lento?

Na maioria dos casos, não: para textos curtos e padrões simples, a execução leva microssegundos. O problema aparece com quantificadores aninhados em entradas grandes ou maliciosas (ReDoS) e ao recompilar o padrão dentro de laços longos — em Python, use re.compile; em JavaScript, declare a regex fora do laço.

Fontes consultadas

Histórico: publicado em . Conteúdo educativo, sem patrocínio das ferramentas citadas. Encontrou um erro? Envie uma correção.

Crédito da imagem: Ilustração gerada por IA para o icardb (uso editorial)

Leia também