Apresentamos a sua atenção a tradução de um breve guia sobre expressões regulares em Java, escrito por Jeff Friesen para o site
javaworld . Para facilitar a leitura, dividimos o artigo em várias partes.
Expressões regulares em Java, Parte 1
Mesclando vários intervalos |
Você pode mesclar vários intervalos em uma única classe de caracteres de intervalo, colocando-os lado a lado. Por exemplo, a classe [a-zA-Z] corresponde a todos os caracteres alfabéticos latinos em letras minúsculas ou maiúsculas. |
Mesclando vários intervalos
Você pode mesclar vários intervalos em uma única classe de caracteres de intervalo, colocando-os lado a lado. Por exemplo, a classe
[a-zA-Z]
corresponde a todos os caracteres alfabéticos latinos em letras minúsculas ou maiúsculas.
Combinando Classes de Personagens
Uma união de classes de caracteres consiste em várias classes de caracteres aninhadas e corresponde a todos os caracteres na união resultante. Por exemplo, a classe
[a-d[m-p]]
corresponde aos caracteres de
a
to
d
e from
m
to
p
. Considere o seguinte exemplo:
java RegexDemo [ab[c-e]] abcdef
Este exemplo encontrará os caracteres
a
,
b
, e , para os quais há correspondências em
c
:
d
e
abcdef
regex = [ab[c-e]]
input = abcdef
Found [a] starting at 0 and ending at 0
Found [b] starting at 1 and ending at 1
Found [c] starting at 2 and ending at 2
Found [d] starting at 3 and ending at 3
Found [e] starting at 4 and ending at 4
Interseção de classe de personagem
A interseção de classes de caracteres consiste em caracteres comuns a todas as classes aninhadas e corresponde apenas aos caracteres comuns. Por exemplo, a classe
[a-z&&[d-f]]
corresponde aos caracteres
d
e . Considere o seguinte exemplo: Observe que no meu sistema operacional Windows, as aspas duplas são necessárias porque o shell de comando as trata como um separador de comandos. Este exemplo encontrará apenas o caractere que corresponde a :
e
f
java RegexDemo "[aeiouy&&[y]]" party
&
y
party
regex = [aeiouy&&[y]]
input = party
Found [y] starting at 4 and ending at 4
Subtraindo classes de personagens
A subtração de classes de caracteres consiste em todos os caracteres, exceto aqueles contidos em classes de caracteres aninhadas, e corresponde apenas aos caracteres restantes. Por exemplo, a classe
[a-z&&[^m-p]]
corresponde aos caracteres de
a
to
l
e from
q
to
z
:
java RegexDemo "[a-f&&[^a-c]&&[^e]]" abcdefg
Este exemplo encontrará os caracteres
d
e
f
para os quais existem correspondências em
abcdefg
:
regex = [a-f&&[^a-c]&&[^e]]
input = abcdefg
Found [d] starting at 3 and ending at 3
Found [f] starting at 5 and ending at 5
Classes de caracteres predefinidos
Algumas classes de caracteres aparecem com frequência suficiente em
expressões regulares para justificar o uso de notação abreviada. A classe
Pattern
oferece classes de caracteres predefinidas como abreviações. Você pode usá-los para simplificar suas expressões regulares e minimizar erros de sintaxe. Existem várias categorias de classes de caracteres predefinidas:
java.lang.Character
propriedades padrão, POSIX e Unicode, como script, bloco, categoria e binário. A lista a seguir mostra apenas a categoria de classes padrão:
\d
: Número. Equivalente [0-9]
.
\D
: Caractere não numérico. Equivalente [^0-9]
.
\s
: Caractere de espaço em branco. Equivalente [ \t\n\x0B\f\r]
.
\S
: Não é um caractere de espaço em branco. Equivalente [^\s]
.
\w
: Símbolo formador de palavras. Equivalente [a-zA-Z_0-9]
.
\W
: Não é um caractere formador de palavras. Equivalente [^\w]
.
O exemplo a seguir usa uma classe de caracteres predefinida
\w
para descrever todos os caracteres de palavra no texto de entrada:
java RegexDemo \w "aZ.8 _"
Observe atentamente os resultados de execução a seguir, que mostram que os caracteres de ponto e espaço não são considerados caracteres de palavra:
regex = \w
input = aZ.8 _
Found [a] starting at 0 and ending at 0
Found [Z] starting at 1 and ending at 1
Found [8] starting at 3 and ending at 3
Found [_] starting at 5 and ending at 5
Separadores de linha |
A documentação da classe SDK Pattern descreve o metacaractere ponto como uma classe de caracteres predefinida que corresponde a qualquer caractere, exceto separadores de linha (sequências de um ou dois caracteres que marcam o final de uma linha). A exceção é o modo pontoll (que discutiremos a seguir), no qual os pontos também correspondem aos separadores de linha. A classe Pattern distingue os seguintes separadores de linha:
- caractere de retorno de carro (
\r );
- caractere de nova linha (símbolo para avançar uma linha do papel) (
\n );
- um caractere de retorno de carro imediatamente seguido por um caractere de nova linha (
\r\n );
- caractere de próxima linha (
\u0085 );
- caractere separador de linha (
\u2028 );
- símbolo separador de parágrafo (
\u2029 )
|
Grupos capturados
O grupo de captura é usado para salvar o conjunto de caracteres encontrado para uso posterior ao pesquisar por padrão. Esta construção é uma sequência de caracteres entre metacaracteres entre parênteses (
( )
). Todos os caracteres dentro do grupo capturado são considerados como um todo ao pesquisar por padrão. Por exemplo, o grupo de captura (
Java
) combina as letras
J
,
a
e em uma única unidade. Este grupo de captura encontra todas as ocorrências do padrão no texto de entrada. A cada partida, os caracteres armazenados anteriormente são substituídos pelos próximos. Os grupos capturados podem ser aninhados em outros grupos capturados. Por exemplo, em uma expressão regular, um grupo está aninhado dentro de um grupo . Cada grupo de captura aninhado ou não aninhado recebe um número, começando em 1, e a numeração vai da esquerda para a direita. No exemplo anterior, corresponde ao grupo de captura número 1 e corresponde ao grupo de captura número 2. Na expressão regular , corresponde ao grupo de captura número 1 e ao grupo de captura número 2. As correspondências armazenadas por grupos de captura podem ser acessadas posteriormente usando referências anteriores. Especificada como uma barra invertida seguida de um caracter numérico correspondente ao número do grupo que está sendo capturado, a referência invertida permite fazer referência a caracteres do texto capturado pelo grupo. Ter um backlink faz com que o matcher se refira ao resultado da pesquisa armazenada do grupo capturado com base no número dele e, em seguida, use os caracteres desse resultado para tentar uma pesquisa adicional. O exemplo a seguir mostra o uso de uma referência anterior para localizar erros gramaticais no texto: Este exemplo usa uma expressão regular para localizar um erro gramatical com uma palavra duplicada imediatamente após o texto de entrada . Esta expressão regular especifica dois grupos a serem capturados: número 1 – , correspondente a e número 2 – , correspondente ao caractere de espaço seguido por . A referência anterior permite que o resultado armazenado do grupo número 2 seja revisitado para que o correspondente possa procurar a segunda ocorrência de um espaço seguido por , imediatamente após a primeira ocorrência de um espaço e . Os resultados do matcher são os seguintes:
v
a
Java
Java
(Java( language))
(language)
(Java)
(Java( language))
(language)
(a)(b)
(a)
(b)
java RegexDemo "(Java( language)\2)" "The Java language language"
(Java( language)\2)
language
Java
"The Java language language"
(Java( language)\2)
Java language language
(language)
language
\2
language
language
RegexDemo
regex = (Java( language)\2)
input = The Java language language
Found [Java language language] starting at 4 and ending at 25
Correspondentes de limite
Às vezes você precisa realizar uma correspondência de padrões no início de uma linha, nos limites das palavras, no final do texto, etc. Você pode fazer isso usando uma das classes edge matchers
Pattern
, que são construções de expressões regulares que procuram correspondências nos seguintes locais:
^
: Início da linha;
$
: Fim da linha;
\b
: Limite da palavra;
\B
: Limite da pseudopalavra;
\A
: Início do texto;
\G
: Fim da partida anterior;
\Z
: Fim do texto, excluindo o separador de linha final (se presente);
\z
: Fim do texto
O exemplo a seguir usa o
^
metacaractere de correspondência de limite para localizar linhas que começam com
The
, seguidas por zero ou mais caracteres de palavra:
java RegexDemo "^The\w*" Therefore
O caractere
^
especifica que os três primeiros caracteres do texto de entrada devem corresponder aos caracteres padrão consecutivos
T
,
h
e
e
, que podem ser seguidos por qualquer número de símbolos formadores de palavras. Aqui está o resultado da execução:
regex = ^The\w*
input = Therefore
Found [Therefore] starting at 0 and ending at 8
O que acontece se você alterar a linha de comando para
java RegexDemo "^The\w*" " Therefore"
? Nenhuma correspondência será encontrada porque
Therefore
o texto de entrada é precedido por um caractere de espaço.
Correspondências de comprimento zero
Às vezes, ao trabalhar com matchers de borda, você encontrará correspondências de comprimento zero.
Совпадение нулевой длины
é uma correspondência que não contém nenhum caractere. Eles podem ocorrer em texto de entrada vazio, no início do texto de entrada, após o último caractere do texto de entrada e entre quaisquer dois caracteres do texto de entrada. As correspondências de comprimento zero são fáceis de reconhecer porque sempre começam e terminam na mesma posição. Considere o seguinte exemplo:
java RegExDemo \b\b "Java is"
Este exemplo procura dois limites de palavras consecutivos e os resultados são assim:
regex = \b\b
input = Java is
Found [] starting at 0 and ending at -1
Found [] starting at 4 and ending at 3
Found [] starting at 5 and ending at 4
Found [] starting at 7 and ending at 6
Vemos várias correspondências de comprimento zero nos resultados. As posições finais aqui são uma a menos que as posições iniciais, pois
RegexDemo
especifiquei no código-fonte na Listagem 1
end() – 1
.
Quantificadores
Um quantificador é uma construção de expressão regular que associa explícita ou implicitamente um padrão a um valor numérico. Este valor numérico determina quantas vezes procurar o padrão. Os quantificadores são divididos em gananciosos, preguiçosos e supergananciosos:
- O quantificador ganancioso (
?
, *
ou +
) é projetado para encontrar a correspondência mais longa. Posso perguntar X
? encontrar uma ou menos ocorrências X
, X*
encontrar zero ou mais ocorrências X
, X+
encontrar uma ou mais ocorrências X
, X{n}
encontrar n
ocorrências X
, X{n,}
encontrar pelo menos (e possivelmente mais) n
ocorrências X
e X{n,m}
encontrar pelo menos , n
mas não mais m
ocorrências X
.
- O quantificador lento (
??
, *?
ou +?
) é projetado para encontrar a correspondência mais curta. Você pode especificar X??
a pesquisa de uma ou menos ocorrências de X
, X*
? encontrar zero ou mais ocorrências X
, X+?
encontrar uma ou mais ocorrências X
, X{n}?
encontrar n
ocorrências X
, X{n,}?
encontrar pelo menos (e possivelmente mais) n
ocorrências X
e X{n,m}?
encontrar pelo menos , n
mas não mais que m
ocorrências X
.
- O quantificador super-ganancioso (
?+
, *+
ou ++
) é semelhante ao quantificador ganancioso, exceto que o quantificador super-ganancioso faz apenas uma tentativa para encontrar a correspondência mais longa, enquanto o quantificador ganancioso pode fazer várias tentativas. Pode ser configurado X?+
para encontrar uma ou menos ocorrências X
, X*+
encontrar zero ou mais ocorrências X
, X++
encontrar uma ou mais ocorrências X
, X{n}+
encontrar n
ocorrências de X
, X{n,}+
encontrar pelo menos (e possivelmente mais) n
ocorrências X
e X{n,m}+
encontrar pelo menos , n
mas não mais que m
ocorrências X
.
O exemplo a seguir ilustra o uso do quantificador ganancioso:
java RegexDemo .*ox "fox box pox"
Aqui estão os resultados:
regex = .*ox
input = fox box pox
Found [fox box pox] starting at 0 and ending at 10
O quantificador ganancioso (
.*
) encontra a sequência mais longa de caracteres terminando em
ox
. Ele consome todo o texto de entrada e depois reverte até detectar que o texto de entrada termina com esses caracteres. Considere agora o quantificador preguiçoso:
java RegexDemo .*?ox "fox box pox"
Seus resultados:
regex = .*?ox
input = fox box pox
Found [fox] starting at 0 and ending at 2
Found [ box] starting at 3 and ending at 6
Found [ pox] starting at 7 and ending at 10
O quantificador lento (
.*?
) encontra a sequência mais curta de caracteres que terminam em
ox
. Ele começa com uma string em branco e gradualmente consome caracteres até encontrar uma correspondência. E então continua trabalhando até que o texto de entrada se esgote. Finalmente, vamos dar uma olhada no quantificador super-ganancioso:
java RegexDemo .*+ox "fox box pox"
E aqui estão seus resultados:
regex = .*+ox
input = fox box pox
O quantificador extra-ganancioso (
.*+
) não encontra correspondências porque consome todo o texto de entrada e não há mais nada para corresponder
ox
no final da expressão regular. Ao contrário do quantificador ganancioso, o quantificador superganancioso não reverte.
Correspondências de comprimento zero
Às vezes, ao trabalhar com quantificadores, você encontrará correspondências de comprimento zero. Por exemplo, usar o seguinte quantificador ganancioso resulta em múltiplas correspondências de comprimento zero:
java RegexDemo a? abaa
Os resultados da execução deste exemplo:
regex = a?
input = abaa
Found [a] starting at 0 and ending at 0
Found [] starting at 1 and ending at 0
Found [a] starting at 2 and ending at 2
Found [a] starting at 3 and ending at 3
Found [] starting at 4 and ending at 3
Existem cinco partidas nos resultados da execução. Embora a primeira, a terceira e a quarta sejam bastante esperadas (correspondem às posições de três letras
a
em
abaa
), a segunda e a quinta podem surpreendê-lo. Parece que indicam o que
a
corresponde
b
ao final do texto, mas na realidade não é o caso. A expressão regular
a?
não pesquisa
b
no final do texto. Ele procura presença ou ausência
a
. Quando
a?
não encontra
a
, ele relata como uma correspondência de comprimento zero.
Expressões de sinalização aninhadas
Os matchers fazem algumas suposições padrão que podem ser substituídas ao compilar a expressão regular em um padrão. Discutiremos esse assunto mais tarde. Uma expressão regular permite substituir qualquer um dos padrões usando uma expressão de sinalização aninhada. Essa construção de expressão regular é especificada como um metacaractere entre parênteses em torno de um metacaractere de ponto de interrogação (
?
), seguido por uma letra latina minúscula. A classe
Pattern
entende as seguintes expressões de sinalização aninhadas:
(?i)
: permite a correspondência de padrões sem distinção entre maiúsculas e minúsculas. Por exemplo, ao usar um comando, java RegexDemo (?i)tree Treehouse
a sequência de caracteres Tree
corresponde ao padrão tree
. O padrão é a pesquisa de padrões que diferencia maiúsculas de minúsculas.
(?x)
: Permite o uso de caracteres de espaço em branco e comentários começando com o metacaractere dentro do padrão #
. O matcher irá ignorar ambos. Por exemplo, para java RegexDemo ".at(?x)#match hat, cat, and so on" matter
uma sequência de caracteres mat
corresponde ao padrão .at
. Por padrão, caracteres de espaço em branco e comentários não são permitidos e o correspondente os trata como caracteres envolvidos na pesquisa.
(?s)
: ativa o modo pontoll, no qual o metacaractere ponto corresponde aos separadores de linha além de qualquer outro caractere. Por exemplo, o comando java RegexDemo (?s). \n
encontrará um caractere de nova linha. O padrão é o oposto de dotall: nenhum separador de linha será encontrado. Por exemplo, o comando Java RegexDemo . \n
não encontrará um caractere de nova linha.
(?m)
: ativa o modo multilinha, onde ^
corresponde ao início e $
ao fim de cada linha. Por exemplo, java RegexDemo "(?m)^abc$" abc\nabc
localiza ambas as sequências no texto de entrada abc
. Por padrão, o modo de linha única é usado: ^
corresponde ao início de todo o texto de entrada e $
ao final dele. Por exemplo, java RegexDemo "^abc$" abc\nabc
retorna uma resposta informando que não há correspondências.
(?u)
: ativa o alinhamento de maiúsculas e minúsculas com distinção entre Unicode. Este sinalizador, quando usado em conjunto com (?i)
, permite a correspondência de padrões sem distinção entre maiúsculas e minúsculas de acordo com o padrão Unicode. A configuração padrão é pesquisar somente caracteres que diferenciam maiúsculas de minúsculas e US-ASCII.
(?d)
: ativa o modo de string no estilo Unix, onde o matcher reconhece metacaracteres em context .
e apenas o separador de linha . O padrão é o modo de string de estilo não Unix: o matcher reconhece, no contexto dos metacaracteres acima, todos os delimitadores de linha.^
$
\n
As expressões de sinalização aninhadas se assemelham a grupos capturados porque seus caracteres são cercados por metacaracteres entre parênteses. Ao contrário dos grupos capturados, as expressões de sinalização aninhadas são um exemplo de grupos não capturados, que são uma construção de expressão regular que não captura caracteres de texto. Eles são definidos como sequências de caracteres entre parênteses.
Especificando múltiplas expressões de sinalizadores aninhados |
É possível especificar múltiplas expressões de sinalização aninhadas em uma expressão regular, colocando-as lado a lado ( (?m)(?i)) ) ou colocando as letras que as definem sequencialmente ( (?mi) ). |
Conclusão
Como você provavelmente já deve ter percebido, as expressões regulares são extremamente úteis e se tornam ainda mais úteis à medida que você domina as nuances de sua sintaxe. Até agora eu apresentei a você o básico sobre expressões regulares e o
Pattern
. Na Parte 2, examinaremos mais profundamente a API Regex e exploraremos os métodos do
Pattern
,
Matcher
e
PatternSyntaxException
. Também mostrarei duas aplicações práticas da API Regex que você pode usar imediatamente em seus programas.
Expressões regulares em Java, Parte 3 Expressões regulares em Java, Parte 4 Expressões regulares em Java, Parte 5
GO TO FULL VERSION