JavaRush /Blogue Java /Random-PT /Expressões regulares em Java, Parte 2

Expressões regulares em Java, Parte 2

Publicado no grupo Random-PT
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 2 - 1Expressõ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 ato de from mto 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:deabcdef
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 de . 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 : efjava RegexDemo "[aeiouy&&[y]]" party&yparty
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 ato le from qto z: java RegexDemo "[a-f&&[^a-c]&&[^e]]" abcdefg Este exemplo encontrará os caracteres de fpara 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 Patternoferece 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.Characterpropriedades 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 \wpara 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 Patterndescreve 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 Patterndistingue 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, ae 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: vaJavaJava(Java( language))(language)(Java)(Java( language))(language)(a)(b)(a)(b)Expressões regulares em Java, Parte 2 - 2java RegexDemo "(Java( language)\2)" "The Java language language"(Java( language)\2)languageJava"The Java language language"(Java( language)\2)Java language language(language)language\2languagelanguageRegexDemo
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, he 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 Thereforeo 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 RegexDemoespecifiquei no código-fonte na Listagem 1 end() – 1. Expressões regulares em Java, Parte 2 a 3

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 nocorrências X, X{n,}encontrar pelo menos (e possivelmente mais) nocorrências Xe X{n,m}encontrar pelo menos , nmas não mais mocorrê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 nocorrências X, X{n,}?encontrar pelo menos (e possivelmente mais) nocorrências Xe X{n,m}?encontrar pelo menos , nmas não mais que mocorrê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 nocorrências de X, X{n,}+encontrar pelo menos (e possivelmente mais) nocorrências Xe X{n,m}+ encontrar pelo menos , nmas não mais que mocorrê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 oxno 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 aem abaa), a segunda e a quinta podem surpreendê-lo. Parece que indicam o que acorresponde bao final do texto, mas na realidade não é o caso. A expressão regular a?não pesquisa bno 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 Patternentende 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 Treehousea sequência de caracteres Treecorresponde 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" matteruma sequência de caracteres matcorresponde 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). \nencontrará um caractere de nova linha. O padrão é o oposto de dotall: nenhum separador de linha será encontrado. Por exemplo, o comando Java RegexDemo . \nnã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\nabclocaliza 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\nabcretorna 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, Matchere 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
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION