O que é expressão regular RegEx?
Na verdade, uma expressão regular (RegEx em Java) é um padrão para procurar uma string no texto. Em Java, a representação inicial desse padrão é sempre uma string, ou seja, um objeto da classe String. No entanto, nem qualquer string pode ser compilada em uma expressão regular, apenas aquelas que seguem as regras para escrever uma expressão regular - a sintaxe definida na especificação da linguagem. Para escrever uma expressão regular, são utilizados caracteres alfabéticos e numéricos, bem como metacaracteres - caracteres que possuem um significado especial na sintaxe das expressões regulares. Por exemplo:String regex = "java"; // string template "java";
String regex = "\\d{3}"; // string template of three numeric characters;
Criando Expressões Regulares em Java
Para criar um RegEx em Java, você precisa seguir duas etapas simples:- escreva-o como uma string usando sintaxe de expressão regular;
- compile esta string em uma expressão regular;
Pattern
. Para fazer isso, você precisa chamar um dos dois métodos estáticos disponíveis na classe compile
. O primeiro método leva um argumento - uma string literal de uma expressão regular, e o segundo - mais outro parâmetro que ativa o modo de comparação do modelo com o texto:
public static Pattern compile (String literal)
public static Pattern compile (String literal, int flags)
A lista de valores de parâmetros possíveis flags
é definida na classe Pattern
e está disponível para nós como variáveis de classe estática. Por exemplo:
Pattern pattern = Pattern.compile("java", Pattern.CASE_INSENSITIVE);//searching for matches with the pattern will be done case-insensitively.
Essencialmente, a classe Pattern
é um construtor de expressões regulares. Nos bastidores, o método compile
chama o construtor privado da classe Pattern
para criar uma visualização compilada. Este método de criação de uma instância de modelo é implementado com o objetivo de criá-la como um objeto imutável. Ao criar, é realizada uma verificação de sintaxe da expressão regular. Caso haja erros na linha, é gerada uma exceção PatternSyntaxException
.
Sintaxe de expressão regular
A sintaxe de expressões regulares é baseada no uso de símbolos<([{\^-=$!|]})?*+.>
, que podem ser combinados com caracteres alfabéticos. Dependendo da sua função, eles podem ser divididos em vários grupos:
Metacaractere | Propósito |
---|---|
^ | início da linha |
$ | fim da linha |
\b | limite da palavra |
\B | não é um limite de palavras |
\A | início da entrada |
\G | final da partida anterior |
\Z | fim da entrada |
\z | fim da entrada |
Metacaractere | Propósito |
---|---|
\d | símbolo digital |
\D | caractere não numérico |
\s | caractere de espaço |
\S | caractere sem espaço em branco |
\c | caractere alfanumérico ou sublinhado |
\C | qualquer caractere que não seja alfabético, numérico ou sublinhado |
. | qualquer personagem |
Metacaractere | Propósito |
---|---|
\t | caractere de tabulação |
\n | caractere de nova linha |
\r | caractere de retorno de carro |
\f | ir para a nova página |
\u0085 | caractere da próxima linha |
\u2028 | caractere separador de linha |
\u2029 | símbolo separador de parágrafo |
Metacaractere | Propósito |
---|---|
[a B C] | qualquer um dos itens acima (a, b ou c) |
[^abc] | qualquer outro além dos listados (não a, b, c) |
[a-zA-Z] | mesclagem de intervalos (caracteres latinos de a a z não diferenciam maiúsculas de minúsculas) |
[anúncio[mp]] | concatenação de caracteres (a a d e m a p) |
[az&&[def]] | intersecção de símbolos (símbolos d,e,f) |
[az&&[^bc]] | subtraindo caracteres (caracteres a, dz) |
Metacaractere | Propósito |
---|---|
? | um ou faltando |
* | zero ou mais vezes |
+ | uma ou mais vezes |
{n} | n vezes |
{n,} | n vezes ou mais |
{n,m} | não menos que n vezes e não mais que m vezes |
Modo quantificador ganancioso
Uma característica especial dos quantificadores é a capacidade de usá-los de diferentes modos: ganancioso, superganancioso e preguiçoso. O modo extra-ganancioso é ativado adicionando o símbolo “+
” após o quantificador, e o modo preguiçoso adicionando o símbolo “ ?
“. Por exemplo:
"A.+a" // greedy mode
"A.++a" // over-greedy mode
"A.+?a" // lazy mode
Usando este modelo como exemplo, vamos tentar entender como os quantificadores funcionam em diferentes modos. Por padrão, o quantificador opera no modo guloso. Isso significa que ele procura a correspondência mais longa possível na string. Como resultado da execução deste código:
public static void main(String[] args) {
String text = "Egor Alla Alexander";
Pattern pattern = Pattern.compile("A.+a");
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
System.out.println(text.substring(matcher.start(), matcher.end()));
}
}
obteremos a seguinte saída: Alla Alexa O algoritmo de busca para um determinado padrão " А.+а
" é realizado na seguinte sequência:
-
No padrão fornecido, o primeiro caractere é a letra russa
А
.Matcher
compara-o com todos os caracteres do texto, começando na posição zero. Na posição zero do nosso texto existe um símboloЕ
, entãoMatcher
ele percorre os caracteres do texto sequencialmente até encontrar uma correspondência com o padrão. No nosso exemplo, este é o símbolo na posição nº 5. -
Depois que uma correspondência é encontrada com o primeiro caractere do padrão,
Matcher
ele verifica a correspondência com o segundo caractere do padrão. No nosso caso, este é o símbolo “.
”, que representa qualquer caractere.Na sexta posição está o símbolo da letra
л
. Claro, corresponde ao padrão "qualquer caractere". -
Matcher
passa para a verificação do próximo caractere do padrão. Em nosso modelo, ele é especificado usando o.+
quantificador “”. Como o número de repetições de “qualquer caractere” no padrão é uma ou mais vezes,Matcher
ele pega o próximo caractere da string e verifica sua conformidade com o padrão, desde que a condição “qualquer caractere” seja atendida, no nosso exemplo - até o final da linha ( da posição nº 7 - nº 18 do texto).Na verdade,
Matcher
ele captura toda a linha até o fim - é aí que sua “ganância” se manifesta. -
Depois de
Matcher
chegar ao final do texto e terminar de verificar aА.+
parte “ ” do padrão, o Matcher começa a verificar o resto do padrão - o caractere da letraа
. Como o texto no sentido direto terminou, a verificação ocorre no sentido inverso, a partir do último caractere: -
Matcher
"lembra" o número de repetições no padrão ".+
" em que chegou ao final do texto, então reduz o número de repetições em uma e verifica o padrão do texto até encontrar uma correspondência:
Modo quantificador ultra-ganancioso
No modo super-ganancioso, o matcher funciona de forma semelhante ao mecanismo do modo ganancioso. A diferença é que quando você pega o texto até o final da linha, não há pesquisa para trás. Ou seja, os três primeiros estágios do modo superganancioso serão semelhantes aos do modo ganancioso. Após capturar a string inteira, o matcher adiciona o restante do padrão e o compara com a string capturada. No nosso exemplo, ao executar o método principal com o padrão "А.++а
", nenhuma correspondência será encontrada.
Modo quantificador lento
-
Neste modo, no estágio inicial, assim como no modo ganancioso, busca-se uma correspondência com o primeiro caractere do padrão:
-
Em seguida, procura uma correspondência com o próximo caractere do padrão - qualquer caractere:
-
Ao contrário do modo ganancioso, o modo preguiçoso procura a correspondência mais curta no texto, portanto, após encontrar uma correspondência com o segundo caractere do padrão, que é especificado por um ponto e corresponde ao caractere na posição nº 6 do texto, ele
Matcher
irá verificar se o texto corresponde ao resto do padrão - o caractere “а
” . -
Como não foi encontrada correspondência com o padrão no texto (na posição nº 7 do texto há o símbolo “
л
“),Matcher
ele adiciona outro “qualquer caractere” no padrão, desde que seja especificado como uma ou mais vezes, e novamente compara o padrão com o texto nas posições nº 5 a nº 8: -
No nosso caso, foi encontrada uma correspondência, mas o final do texto ainda não foi alcançado. Portanto, a partir da posição nº 9, a verificação começa buscando o primeiro caractere do padrão usando um algoritmo semelhante e depois se repete até o final do texto.
main
ao utilizar o А.+?а
template " ", obteremos o seguinte resultado: Alla Alexa Como pode ser visto em nosso exemplo, ao usar diferentes modos de quantificador para o mesmo template, obtivemos resultados diferentes. Portanto, é necessário levar em consideração esta característica e selecionar o modo desejado dependendo do resultado desejado durante a busca.
Escape de caracteres em expressões regulares
Como uma expressão regular em Java, ou mais precisamente sua representação inicial, é especificada usando uma string literal, é necessário levar em consideração as regras da especificação Java que se relacionam com literais de string. Em particular, o caractere de barra invertida "\
" em literais de string no código-fonte Java é interpretado como um caractere de escape que alerta o compilador de que o caractere que o segue é um caractere especial e deve ser interpretado de uma maneira especial. Por exemplo:
String s = "The root directory is \nWindows";//wrap Windows to a new line
String s = "The root directory is \u00A7Windows";//insert paragraph character before Windows
Portanto, em literais de string que descrevem uma expressão regular e usam o \
caractere " " (por exemplo, para metacaracteres), ela deve ser duplicada para que o compilador de bytecode Java não a interprete de forma diferente. Por exemplo:
String regex = "\\s"; // template for searching for space characters
String regex = "\"Windows\""; // pattern to search for the string "Windows"
O caractere de barra invertida dupla também deve ser usado para escapar de caracteres especiais se planejarmos usá-los como caracteres "regulares". Por exemplo:
String regex = "How\\?"; // template for searching the string "How?"
Métodos da classe Pattern
A classePattern
possui outros métodos para trabalhar com expressões regulares: String pattern()
– retorna a representação em string original da expressão regular a partir da qual o objeto foi criado Pattern
:
Pattern pattern = Pattern.compile("abc");
System.out.println(Pattern.pattern())//"abc"
static boolean matches(String regex, CharSequence input)
– permite verificar a expressão regular passada no parâmetro regex em relação ao texto passado no parâmetro input
. Retorna: true – se o texto corresponder ao padrão; falso – caso contrário; Exemplo:
System.out.println(Pattern.matches("A.+a","Alla"));//true
System.out.println(Pattern.matches("A.+a","Egor Alla Alexander"));//false
int flags()
– retorna os flags
valores dos parâmetros do modelo que foram definidos quando ele foi criado ou 0 se este parâmetro não foi definido. Exemplo:
Pattern pattern = Pattern.compile("abc");
System.out.println(pattern.flags());// 0
Pattern pattern = Pattern.compile("abc",Pattern.CASE_INSENSITIVE);
System.out.println(pattern.flags());// 2
String[] split(CharSequence text, int limit)
– divide o texto passado como parâmetro em um array de elementos String
. O parâmetro limit
determina o número máximo de correspondências pesquisadas no texto:
- quando
limit>0
– a busca porlimit-1
correspondências é realizada; - at
limit<0
– procura todas as correspondências no texto - quando
limit=0
– procura todas as correspondências no texto, enquanto as linhas vazias no final do array são descartadas;
public static void main(String[] args) {
String text = "Egor Alla Anna";
Pattern pattern = Pattern.compile("\\s");
String[] strings = pattern.split(text,2);
for (String s : strings) {
System.out.println(s);
}
System.out.println("---------");
String[] strings1 = pattern.split(text);
for (String s : strings1) {
System.out.println(s);
}
}
Saída do console: Egor Alla Anna -------- Egor Alla Anna Consideraremos outro método de classe para criar um objeto Matcher
abaixo.
Métodos de classe correspondente
Matcher
é uma classe a partir da qual um objeto é criado para procurar padrões. Matcher
– este é um “motor de busca”, um “motor” de expressões regulares. Para pesquisar, ele precisa receber duas coisas: um padrão de pesquisa e um “endereço” para pesquisar. Para criar um objeto, Matcher
o seguinte método é fornecido na classe Pattern
: рublic Matcher matcher(CharSequence input)
Como argumento, o método leva uma sequência de caracteres na qual a pesquisa será realizada. Estes são objetos de classes que implementam a interface CharSequence
. String
Você pode passar não apenas , mas também , StringBuffer
e StringBuilder
como argumento . O modelo de pesquisa é o objeto de classe no qual o método é chamado . Exemplo de criação de um matcher: Segment
CharBuffer
Pattern
matcher
Pattern p = Pattern.compile("a*b");// compiled the regular expression into a view
Matcher m = p.matcher("aaaaab");//created a search engine in the text “aaaaab” using the pattern "a*b"
Agora, com a ajuda do nosso “mecanismo de busca”, podemos procurar correspondências, descobrir a posição da correspondência no texto e substituir o texto usando métodos de classe. O método boolean find()
procura a próxima correspondência no texto com o padrão. Usando este método e o operador de loop, você pode analisar todo o texto de acordo com o modelo de evento (realizar as operações necessárias quando ocorre um evento - encontrar uma correspondência no texto). Por exemplo, usando os métodos desta classe, int start()
você int end()
pode determinar as posições da correspondência no texto e, usando os métodos String replaceFirst(String replacement)
, String replaceAll(String replacement)
substituir as correspondências no texto por outro texto de substituição. Exemplo:
public static void main(String[] args) {
String text = "Egor Alla Anna";
Pattern pattern = Pattern.compile("A.+?a");
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
int start=matcher.start();
int end=matcher.end();
System.out.println("Match found" + text.substring(start,end) + " с "+ start + " By " + (end-1) + "position");
}
System.out.println(matcher.replaceFirst("Ira"));
System.out.println(matcher.replaceAll("Olga"));
System.out.println(text);
}
Saída do programa: Foi encontrada uma correspondência Alla de 5 a 8 posições Uma correspondência foi encontrada Anna de 10 a 13 posições Egor Ira Anna Egor Olga Olga Egor Alla Anna Pelo exemplo fica claro que os métodos replaceFirst
criam replaceAll
um novo objeto String
- uma string, que é o texto fonte no qual as correspondências com o modelo são substituídas pelo texto passado ao método como argumento. Além disso, o método replaceFirst
substitui apenas a primeira correspondência e replaceAll
todas as correspondências no teste. O texto original permanece inalterado. O uso de outros métodos de classe Matcher
, bem como exemplos de expressões regulares, pode ser encontrado nesta série de artigos . As operações mais comuns com expressões regulares ao trabalhar com texto são de classes Pattern
e Matcher
são incorporadas ao arquivo String
. Esses são métodos como split
, matches
, replaceFirst
, replaceAll
. Mas, na verdade, "sob o capô" eles usam o Pattern
e Matcher
. Portanto, se você precisar substituir texto ou comparar strings em um programa sem escrever código desnecessário, use os métodos do String
. Se você precisar de recursos avançados, pense em classes Pattern
e Matcher
.
Conclusão
Uma expressão regular é descrita em um programa Java usando strings que correspondem a um padrão definido pelas regras. Quando o código é executado, Java recompila essa string em um objeto de classePattern
e usa o objeto de classe Matcher
para encontrar correspondências no texto. Como falei no início, muitas vezes as expressões regulares são deixadas de lado para depois, por serem consideradas um tema difícil. No entanto, se você entender o básico de sintaxe, metacaracteres, escape e estudar exemplos de expressões regulares, eles serão muito mais simples do que parecem à primeira vista.
GO TO FULL VERSION