Expressões Regulares: Um Guia para Iniciantes
· 12 min de leitura
Índice
O que é Regex?
Expressões regulares, comumente abreviadas como regex ou regexp, são sequências de caracteres que definem padrões de busca. Essas ferramentas poderosas são usadas extensivamente para correspondência de strings, validação e manipulação dentro de dados de texto. Ao dominar regex, você pode automatizar tarefas como validação de texto, extração de dados e formatação de dados com eficiência notável.
À primeira vista, regex pode parecer intimidante devido à sua sintaxe densa e críptica. No entanto, entender seus componentes principais abre portas para técnicas sofisticadas de manipulação de dados que, de outra forma, exigiriam centenas de linhas de código procedural. Pense em regex como uma mini-linguagem especializada projetada especificamente para correspondência de padrões.
Você encontrará regex em inúmeros cenários do mundo real: desenvolvimento de software, análise de dados, administração de sistemas, gerenciamento de conteúdo e web scraping. Casos de uso comuns incluem análise de logs, validação de formulários, transformação de dados em arquivos CSV, operações de buscar e substituir e extração de informações estruturadas de texto não estruturado.
Dica profissional: Expressões regulares são suportadas em praticamente todas as linguagens de programação modernas, incluindo JavaScript, Python, Java, PHP, Ruby e Go. Elas também estão integradas em editores de texto como VS Code, Sublime Text e ferramentas de linha de comando como grep e sed.
Entendendo a Sintaxe Regex
A sintaxe de regex é construída sobre elementos fundamentais que se combinam para criar capacidades poderosas de correspondência de padrões. Embora a notação possa parecer críptica inicialmente, cada símbolo serve a um propósito específico na definição de qual texto deve corresponder ao seu padrão.
Vamos detalhar os blocos de construção essenciais que formam a base de cada padrão regex. Entender esses elementos principais permitirá que você construa padrões para praticamente qualquer cenário de correspondência de texto.
Metacaracteres Básicos
Metacaracteres são caracteres especiais em regex que têm significados específicos em vez de corresponder a si mesmos literalmente. Aqui estão os mais fundamentais:
.(ponto): Corresponde a qualquer caractere único, exceto uma nova linha. Por exemplo,a.ccorresponde a "abc", "a2c", "a@c", mas não "ac".\(barra invertida): Escapa caracteres especiais para correspondê-los literalmente. Use\.para corresponder a um ponto real.|(pipe): Atua como um operador OU. O padrãocat|dogcorresponde a "cat" ou "dog".
Quando você precisa corresponder a um metacaractere literalmente (como procurar por um asterisco ou ponto real), você deve escapá-lo com uma barra invertida. Por exemplo, \* corresponde a um caractere asterisco literal.
Dica rápida: Use nosso Testador de Correspondência Regex para experimentar com padrões em tempo real e ver exatamente o que seu regex corresponde.
Classes de Caracteres e Intervalos
Classes de caracteres permitem que você corresponda a qualquer caractere de um conjunto específico. Elas são colocadas entre colchetes e fornecem uma maneira concisa de especificar múltiplos caracteres possíveis em uma única posição.
Classes de Caracteres Básicas
[abc]: Corresponde a qualquer caractere único que seja 'a', 'b' ou 'c'.[^abc]: Corresponde a qualquer caractere exceto 'a', 'b' ou 'c'. O circunflexo dentro dos colchetes nega a classe.[a-z]: Corresponde a qualquer letra minúscula de 'a' a 'z'.[A-Z]: Corresponde a qualquer letra maiúscula.[0-9]: Corresponde a qualquer dígito de 0 a 9.[a-zA-Z0-9]: Corresponde a qualquer caractere alfanumérico.
Você pode combinar múltiplos intervalos dentro de uma única classe de caracteres. Por exemplo, [a-zA-Z0-9_] corresponde a qualquer letra, dígito ou sublinhado—comumente usado para validar nomes de usuário ou nomes de variáveis.
Classes de Caracteres Predefinidas
A maioria dos mecanismos regex fornece classes de caracteres abreviadas para padrões comuns:
| Abreviação | Equivalente | Descrição |
|---|---|---|
\d |
[0-9] |
Qualquer dígito |
\D |
[^0-9] |
Qualquer não-dígito |
\w |
[a-zA-Z0-9_] |
Qualquer caractere de palavra |
\W |
[^a-zA-Z0-9_] |
Qualquer caractere não-palavra |
\s |
[ \t\n\r\f\v] |
Qualquer caractere de espaço em branco |
\S |
[^ \t\n\r\f\v] |
Qualquer caractere não-espaço em branco |
Essas classes abreviadas tornam seus padrões mais legíveis e fáceis de manter. Por exemplo, \d{3}-\d{3}-\d{4} é muito mais claro do que [0-9]{3}-[0-9]{3}-[0-9]{4} para corresponder números de telefone.
Quantificadores Explicados
Quantificadores especificam quantas vezes um elemento deve ocorrer em seu padrão. Eles são colocados após o elemento que modificam e são essenciais para corresponder padrões de comprimento variável.
Quantificadores Básicos
*: Corresponde a zero ou mais ocorrências. O padrãoab*ccorresponde a "ac", "abc", "abbc", "abbbc", etc.+: Corresponde a uma ou mais ocorrências. O padrãoab+ccorresponde a "abc", "abbc", mas não "ac".?: Corresponde a zero ou uma ocorrência (torna o elemento anterior opcional). O padrãocolou?rcorresponde tanto a "color" quanto a "colour".
Quantificadores Específicos
Para controle preciso sobre contagens de repetição, use chaves:
{n}: Corresponde exatamente a n ocorrências.\d{4}corresponde exatamente a quatro dígitos.{n,}: Corresponde a n ou mais ocorrências.\d{3,}corresponde a três ou mais dígitos.{n,m}: Corresponde entre n e m ocorrências (inclusive).\d{2,4}corresponde a 2, 3 ou 4 dígitos.
Quantificadores Gananciosos vs. Preguiçosos
Por padrão, quantificadores são "gananciosos"—eles correspondem ao máximo de texto possível. Adicionar um ponto de interrogação após um quantificador o torna "preguiçoso" ou "não-ganancioso", correspondendo ao mínimo possível.
Considere a string "<div>content</div>":
<.+>(ganancioso) corresponde à string inteira do primeiro<ao último><.+?>(preguiçoso) corresponde apenas a<div>, depois</div>separadamente
Dica profissional: Quantificadores preguiçosos são cruciais ao analisar HTML, XML ou quaisquer estruturas aninhadas. Eles evitam que seu padrão corresponda a muito conteúdo entre delimitadores.
Âncoras e Limites
Âncoras não correspondem a caracteres—elas correspondem a posições dentro do texto. Elas são essenciais para garantir que os padrões correspondam em locais específicos em vez de em qualquer lugar na string.
Âncoras de Posição
^: Corresponde ao início de uma linha ou string.^Hellocorresponde a "Hello" apenas no início.$: Corresponde ao final de uma linha ou string.world$corresponde a "world" apenas no final.\A: Corresponde ao início absoluto da string (não afetado pelo modo multilinha).\Z: Corresponde ao final absoluto da string (não afetado pelo modo multilinha).
Combinar âncoras de início e fim garante que a string inteira corresponda ao seu padrão. Por exemplo, ^\d{5}$ corresponde a uma string que contém exatamente cinco dígitos e nada mais—perfeito para validar códigos postais dos EUA.
Limites de Palavra
Limites de palavra são incrivelmente úteis para corresponder palavras inteiras sem corresponder acidentalmente a partes de palavras maiores:
\b: Corresponde a um limite de palavra (a posição entre um caractere de palavra e um caractere não-palavra).\B: Corresponde a um não-limite de palavra.
O padrão \bcat\b corresponde a "cat" como uma palavra independente, mas não o "cat" em "category" ou "concatenate". Isso é essencial para operações de buscar e substituir onde você deseja atingir palavras específicas.
Grupos e Captura
Grupos permitem que você trate múltiplos caracteres como uma única unidade e capture texto correspondido para uso posterior. Eles são fundamentais para extrair dados e criar padrões complexos.
Grupos de Captura
Parênteses criam grupos de captura que lembram o texto correspondido:
(\d{3})-(\d{3})-(\d{4})
Este padrão corresponde a um número de telefone e captura três grupos: código de área, prefixo e número da linha. Você pode referenciar esses grupos capturados em strings de substituição ou extraí-los programaticamente.
Na maioria das linguagens de programação, grupos capturados são numerados começando de 1. O grupo 0 sempre se refere à correspondência inteira. Por exemplo, em JavaScript:
const regex = /(\d{3})-(\d{3})-(\d{4})/;
const match = "555-123-4567".match(regex);
// match[0] = "555-123-4567" (correspondência completa)
// match[1] = "555" (primeiro grupo)
// match[2] = "123" (segundo grupo)
// match[3] = "4567" (terceiro grupo)
Grupos Não-Capturadores
Às vezes você precisa de agrupamento para aplicar quantificadores ou alternância, mas não precisa capturar o texto correspondido. Use (?:...) para grupos não-capturadores:
(?:https?|ftp)://[^\s]+
Isso corresponde a URLs começando com http, https ou ftp sem criar um grupo de captura separado para o protocolo. Grupos não-capturadores melhoram o desempenho e mantêm sua numeração de grupos de captura limpa.
Grupos de Captura Nomeados
Grupos nomeados tornam seu regex mais legível e sustentável ao atribuir nomes significativos ao texto capturado:
(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})
Em vez de lembrar que o grupo 1 é o ano, você pode referenciá-lo pelo nome. A sintaxe varia ligeiramente entre mecanismos regex, mas a maioria das implementações modernas suporta grupos nomeados.
Técnicas Avançadas de Regex
Uma vez que você dominou o básico, essas técnicas avançadas ajudarão você a enfrentar desafios complexos de correspondência de padrões.
Asserções Lookahead e Lookbehind
Asserções lookaround verificam se um padrão existe à frente ou atrás da posição atual sem incluí-lo na correspondência:
| Asserção | Sintaxe | Descrição |
|---|---|---|
| Lookahead Positivo | (?=...) |
Corresponde se seguido pelo padrão |
| Lookahead Negativo | (?!...) |
Corresponde se NÃO seguido pelo padrão |
| Lookbehind Positivo | (?<=...) |
Corresponde se precedido pelo padrão |
| Lookbehind Negativo | (?<!...) |
Corresponde se NÃO precedido pelo padrão |
Exemplo: \d+(?= dollars) corresponde a números seguidos por " dollars", mas não inclui " dollars" na correspondência. Isso é útil quando você quer extrair valores que aparecem em contextos específicos.
Referências Retroativas
Referências retroativas permitem que você corresponda ao mesmo texto que foi previamente capturado por um grupo. Elas são numeradas com notação de barra invertida:
\b(\w+)\s+\1\b
Este padrão corresponde a palavras repetidas como "the the" ou "is is". O \1 se refere de volta ao que foi capturado pelo primeiro grupo, garantindo que ambas as palavras sejam idênticas.
Padrões Condicionais
Alguns mecanismos regex suportam padrões condicionais que correspondem a diferentes alternativas com base em se um grupo anterior correspondeu:
(a)?b(?(1)c|d)
Isso corresponde a "abc" se o "a" opcional estava presente, ou "bd" se não estava. Padrões condicionais são poderosos, mas podem tornar o regex mais difícil de ler, então use-os criteriosamente.
Dica profissional: Recursos avançados como lookarounds e condicionais não são suportados em todos os mecanismos regex. Sempre verifique a documentação da sua linguagem de programação ou ferramenta para compatibilidade.
Aplicações Práticas
Vamos explorar cenários do mundo real onde regex brilha, completo com exemplos práticos que você pode usar imediatamente.
Validação de Email
Embora a validação perfeita de email seja surpreendentemente com