Sintaxe de Regex em Java
Sintaxe de expressões regulares em Java — caracteres, classes, âncoras, quantificadores e construções especiais.
Uma expressão regular é uma pequena linguagem de padrões para descrever texto. O Java a implementa no pacote java.util.regex, e a sintaxe é o dialeto estilo Perl compartilhado pela maioria das linguagens modernas — com uma particularidade específica do Java: cada barra invertida em um padrão deve ser duplicada em um literal de string Java, pois o compilador consome uma antes que o motor de regex a veja. Este capítulo é uma referência dessa sintaxe: os blocos de construção que você combina para corresponder, pesquisar e validar texto.
Se você é novo em expressões regulares em Java, comece com a Introdução ao Java Regex, e volte aqui quando precisar da folha de referência completa da sintaxe.
Literais e metacaracteres
A maioria dos caracteres em um padrão corresponde a si mesma: cat corresponde às três letras c, a, t. O poder vem dos metacaracteres — caracteres com significado especial que você combina em regras. Os doze que o motor trata de forma especial são:
. ^ $ * + ? ( ) [ ] { } | \Para corresponder a um desses literalmente, escape-o com uma barra invertida. Lembre-se da regra da barra invertida dupla para código-fonte Java: um regex \. é escrito como "\\." no código.
Pattern.matches("a.c", "abc"); // true — '.' matches any char
Pattern.matches("a.c", "a.c"); // true — '.' also matches a literal dot
Pattern.matches("a\\.c", "abc"); // false — '\.' matches ONLY a literal dot
Pattern.matches("a\\.c", "a.c"); // trueClasses de caracteres
Uma classe de caracteres entre colchetes corresponde a qualquer um caractere de um conjunto. Intervalos usam um hífen, e um ^ inicial nega o conjunto.
"[aeiou]" // any one lowercase vowel
"[a-z]" // any one lowercase letter
"[A-Za-z0-9]" // any letter or digit
"[^0-9]" // any character that is NOT a digitO Java também oferece classes predefinidas como abreviações. Estas são as que você usa constantemente:
| Abreviação | Equivalente | Correspondências |
|---|---|---|
. | — | Qualquer caractere, exceto um terminador de linha |
\d | [0-9] | Um dígito |
\D | [^0-9] | Um não-dígito |
\w | [a-zA-Z0-9_] | Um caractere de palavra |
\W | [^a-zA-Z0-9_] | Um caractere que não é de palavra |
\s | [ \t\n\x0B\f\r] | Um caractere de espaço em branco |
\S | [^\s] | Um caractere que não é de espaço em branco |
A forma maiúscula é sempre a negação da forma minúscula. Consulte Classes de Caracteres em Java Regex para o conjunto completo, incluindo classes POSIX e Unicode.
Quantificadores: greedy, reluctant e possessive
Um quantificador indica quantas vezes o elemento anterior pode se repetir. Por padrão, os quantificadores são greedy (gananciosos) — eles pegam o máximo possível e recuam se o restante do padrão precisar. Adicione ? para tornar um quantificador reluctant (relutante, que corresponde o mínimo possível) ou + para torná-lo possessive (possessivo, que pega e nunca devolve).
| Quantificador | Significado |
|---|---|
* | Zero ou mais |
+ | Um ou mais |
? | Zero ou um (opcional) |
{n} | Exatamente n |
{n,} | Pelo menos n |
{n,m} | Entre n e m |
"\\d{3}" // exactly three digits
"\\d{2,4}" // two to four digits
"a+" // one or more 'a'
"colou?r" // matches "color" and "colour"
"<.+>" // greedy: on "<a><b>" matches the whole "<a><b>"
"<.+?>" // reluctant: on "<a><b>" matches just "<a>"Para uma análise mais aprofundada dos comportamentos greedy, reluctant e possessive, leia Quantificadores em Java Regex.
Âncoras, limites e alternância
Âncoras correspondem a uma posição, não a um caractere. ^ é o início da entrada (ou da linha, no modo multilinha), $ é o fim, e \b é um limite de palavra — a posição de largura zero entre um \w e um \W. A alternância com | corresponde a qualquer um dos lados.
"^Hello" // "Hello" only at the start
"\\.txt$" // ".txt" only at the end
"\\bcat\\b" // "cat" as a whole word, not inside "category"
"cat|dog" // "cat" or "dog"
"^(cat|dog)$" // the whole string is exactly "cat" or "dog"Observe que | tem precedência muito baixa: ^cat|dog$ significa (^cat)|(dog$), não ^(cat|dog)$. Envolva as alternativas em um grupo quando quiser que as âncoras se apliquem a ambos os lados.
Grupos, retrorreferências e flags inline
Parênteses criam um grupo de captura — o motor lembra o que cada grupo correspondeu, numerado da esquerda para a direita a partir de 1. (?:...) é um grupo não-capturante quando você só precisa aplicar um quantificador. Uma retrorreferência \1 corresponde ao mesmo texto que o primeiro grupo capturou. Flags inline como (?i) alteram o comportamento de correspondência sem um flag separado em Pattern.compile.
"(\\d{4})-(\\d{2})" // group 1 = year, group 2 = month
"(?:ab)+" // repeats "ab" without capturing it
"(\\w+) \\1" // a word followed by itself ("the the")
"(?i)java" // case-insensitive: matches "Java", "JAVA"
"(?m)^line" // multiline: ^ matches at each line startOs grupos de captura têm seu próprio capítulo — Grupos em Java Regex cobre grupos nomeados e como ler o texto capturado de um Matcher. Flags inline como (?i) e (?m) são os equivalentes in-pattern dos flags de Pattern.compile descritos em Flags de Java Regex.
Um exemplo prático: as construções em ação
Este programa utiliza uma classe de dígitos com um quantificador, alternância ancorada, uma retrorreferência, correspondência greedy versus reluctant, a abreviação \w+ e um flag de insensibilidade a maiúsculas/minúsculas inline — tudo usando apenas java.util.regex. A sintaxe aqui impulsiona a API Pattern e Matcher abordada em Pattern e Matcher em Java Regex.
O que observar na execução:
\d{4}encontrou tanto1995quanto2011porquefind()busca cada correspondência na entrada, enquanto uma classe mais quantificador (\drepetido{4}vezes) é a forma canônica de corresponder a um campo de largura fixa. A barra invertida dupla em"\\d{4}"é o literal de string Java que produz a barra invertida simples que o motor de regex espera.Pattern.matches("cat|dog", "dog")retornoutrue, mas o mesmo padrão em"catnap"retornoufalse—matches()ancora implicitamente a entrada inteira, então, mesmo quecatapareça emcatnap, onaprestante fica sem correspondência e a correspondência geral falha.- A retrorreferência
\1transformou(\w+) \1em "uma palavra seguida pela mesma palavra", que é o motivo pelo qual reportoutheeis— as duas repetições — e ignorou toda palavra que não foi repetida imediatamente. As retrorreferências correspondem ao texto capturado, não ao padrão novamente. - Na mesma entrada
<a><b>, o greedy<.+>consumiu toda a string, enquanto o reluctant<.+?>parou no primeiro>, retornando apenas<a>. Este único contraste é a correção de bug de regex mais comum que você fará: adicione?a um quantificador quando ele captura demais. \w+contou 3 tokens emab, cd-ef!—ab,cdeef— porque,,-e!são todos caracteres\W(não-palavras) que quebram uma sequência de caracteres de palavra. O flag inline(?i)então correspondeujavaaJAVA, mostrando que os flags podem residir dentro do próprio padrão em vez de somente emPattern.compile.