W3docs

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"); // true

Classes 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 digit

O Java também oferece classes predefinidas como abreviações. Estas são as que você usa constantemente:

AbreviaçãoEquivalenteCorrespondê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).

QuantificadorSignificado
*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 start

Os 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.

java— editable, runs on the server

O que observar na execução:

  • \d{4} encontrou tanto 1995 quanto 2011 porque find() busca cada correspondência na entrada, enquanto uma classe mais quantificador (\d repetido {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") retornou true, mas o mesmo padrão em "catnap" retornou falsematches() ancora implicitamente a entrada inteira, então, mesmo que cat apareça em catnap, o nap restante fica sem correspondência e a correspondência geral falha.
  • A retrorreferência \1 transformou (\w+) \1 em "uma palavra seguida pela mesma palavra", que é o motivo pelo qual reportou the e is — 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 em ab, cd-ef!ab, cd e ef — 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 correspondeu java a JAVA, mostrando que os flags podem residir dentro do próprio padrão em vez de somente em Pattern.compile.

Prática

Prática
Na entrada '<a><b>', por que o regex '<.+>' corresponde à string inteira '<a><b>' enquanto '<.+?>' corresponde apenas a '<a>'?
Na entrada '<a><b>', por que o regex '<.+>' corresponde à string inteira '<a><b>' enquanto '<.+?>' corresponde apenas a '<a>'?
Was this page helpful?