Livro de receitas Expressões regulares em Java

utilizando Java 11

Cada receita exemplifica um tópico de expressão regular

Expressão regular é uma sequência de caracteres que especifica um padrão de busca em uma determinada entrada. Entrada aqui é entendida como qualquer string onde a busca será efetuada.

Além de verificar a existência de determinados padrões em uma entrada, podemos também obter a sua posição na entrada, removê-los e substituí-los.

Conteúdo

  1. Verificar existência de uma letra em uma string
  2. Verificar quantas correspondências de uma letra há em uma string
  3. Exibir correspondência
  4. Obter a posição inicial e final de uma correspondência
  5. Reiniciando a busca na entrada
  6. Definindo expressões regulares
  7. Verificar se a entrada inteira corresponde à expressão regular
  8. Manter o resultado de uma correspondência após próximo Matcher#find
  9. Expressão regular ignorando caixa das letras
  10. Expressão regular com classes de caracteres Unicode
  11. Expressão regular aplicada em cada linha da entrada
  12. Expressão regular com metacaracteres interpretados literalmente
  13. Divisão de strings como vetor
  14. Divisão de strings como stream
  15. Matcher#find como Predicate: remover de stream elementos sem correspondências
  16. Matcher#matches como Predicate: remover de stream elementos não correpondentes
  17. Stream de correspondências
  18. String com correspondências substituídas por literal
  19. String com correspondências substituídas por barra invertida ou cifrão
  20. String com algumas correspondências substituídas por literal
  21. String com correspondências substituídas por função
  22. Referências

👉 Algum conceito faltando?

Deixe um comentário no fim do post e escreverei a receita assim que possível.

Verificar existência de uma letra em uma string

  1. Chame Pattern#compile com uma expressão regular como argumento para criar um objeto Pattern.
  2. Crie um objeto Matcher invocando o método matcher() de Pattern, passando como argumento a entrada a ser analisada.
  3. Por fim, chame o método find() de Matcher para tentar encontrar uma correspondência entre a expressão regular e os caracteres da entrada. Caso uma correspondência seja encontrada find() devolverá true.
package dev.caiosantesso.regex;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class CorrespondenciaParcial {
  public static void main(String[] args) {
    String entrada = "Uma frase";
    String regex = "f";

    Pattern padrao = Pattern.compile(regex);
    Matcher matcher = padrao.matcher(entrada);

    boolean corresponde = matcher.find();
    System.out.printf("'%s' tem correspondência do padrão '%s'? %b",
        entrada, padrao, corresponde);
    // 'Uma frase' tem correspondência do padrão 'f'? true
  }
}

Verificar quantas correspondências de uma letra há em uma string

  1. Crie um objeto Pattern.
  2. A partir dele, instancie um Matcher.
  3. O método find() de Matcher retorna true para cada correspondência encontrada em uma entrada. Então chame find() até obter false.

⚠️ Matcher armazena a posição da última correspondência na entrada. Cada chamada subsequente à find() é iniciada a partir da última posição armazenada.

package dev.caiosantesso.regex;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class CorrespondenciasParciais {
  public static void main(String[] args) {
    String entrada = "Essa frase tem seis s.";
    String regex = "s";

    Pattern padrao = Pattern.compile(regex);
    Matcher matcher = padrao.matcher(entrada);

    int correspondencias = 0;
    while (matcher.find()) {
      correspondencias++;
    }
    System.out.println(correspondencias); // 6
  }
}

Exibir correspondência

  1. Crie um objeto Pattern.
  2. A partir dele, instancie um Matcher.
  3. Invoque Matcher#find para tentar encontrar a próxima correspondência.
  4. Caso a correspondência seja encontrada, chame group() para obter a ocorrência em string.
  5. Repita os dois últimos passos para exibir demais correspondências.
package dev.caiosantesso.regex;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ExibirCorrespondencias {
  public static void main(String[] args) {
    String entrada = "Açafrão.";
    String regexLetraAsciiOuDigito = "\\w";

    Pattern padrao = Pattern.compile(regexLetraAsciiOuDigito);
    Matcher matcher = padrao.matcher(entrada);

    while (matcher.find()) {
      String correspondencia = matcher.group();
      System.out.printf("%s | ", correspondencia);
    } // A | a | f | r | o |
  }
}

Obter a posição inicial e final de uma correspondência

  1. Crie um objeto Pattern.
  2. A partir dele, instancie um Matcher.
  3. Invoque Matcher#find para tentar encontrar a próxima correspondência.
  4. Caso a correspondência seja encontrada, chame start() para obter a posição inicial da ocorrência na entrada e end() a final.
  5. Repita os dois últimos passos para obter demais posições de correspondências na entrada.
package dev.caiosantesso.regex;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class PosicaoDaCorrespondencia {
  public static void main(String[] args) {
    String entrada = "Não, ação e peão.";
    String regex = ".ão";

    Pattern padrao = Pattern.compile(regex);
    Matcher matcher = padrao.matcher(entrada);

    while (matcher.find()) {
      int inicio = matcher.start();
      int fim = matcher.end();
      String s = entrada.substring(inicio, fim);
      System.out.printf("| %d - %d %s ", inicio, fim, s);
    }
    // | 0 - 3 Não | 6 - 9 ção | 13 - 16 eão
  }
}

Reiniciando a busca na entrada

  1. Quando Matcher#find retorna false significa que toda a entrada foi consumida. Para reiniciar a busca invoque reset().
package dev.caiosantesso.regex;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ReiniciarBuscasNaEntrada {
  public static void main(String[] args) {
    String entrada = "AA";
    String regex = "A";

    Pattern padrao = Pattern.compile(regex);
    Matcher matcher = padrao.matcher(entrada);

    int i = 0;
    for (; matcher.find(); i++) ;
    System.out.printf("#1: %d\n", i); //#1: 2

    matcher.reset();

    for (; matcher.find(); i++) ;
    System.out.printf("#1 e #2: %d\n", i); //#1 e #2: 4
  }
}

Definindo expressões regulares

A classe abaixo gera as saídas de cada subseção.

Cada subseção exemplifica um aspecto na definição de uma expressão regular.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package dev.caiosantesso.regex;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ExpressaoRegular {
  static String e = "A Wikipédia foi lançada no dia 15.01.01.";

  private static void exibeSetas(Matcher matcher) {
    var linha = new StringBuilder(" ".repeat(e.length()));
    while (matcher.find()) {
      var setas = "↑".repeat(matcher.group()
                                        .length());
      linha.replace(matcher.start(), matcher.end(), setas);
    }
    System.out.println(linha);
  }

  private static void exibeTabela(Matcher matcher) {
    var formato = "%-10s%-10s%-10s%n";
    System.out.printf(formato, "Sequência", "Início", "Fim");
    while (matcher.find())
      System.out.printf(formato, matcher.group(), matcher.start(),
          matcher.end());
  }

  private static void exibeQuadro(String padrao) {
    Pattern pattern = Pattern.compile(padrao);
    Matcher matcher = pattern.matcher(e);

    System.out.printf("Regex: %s%n%s%n", padrao, e);
    exibeSetas(matcher);
    matcher.reset();
    exibeTabela(matcher);
    System.out.println("\n");
  }

  public static void main(String[] args) {
    exibeQuadro("o");
    exibeQuadro("dia");
    exibeQuadro(" ");
    exibeQuadro("\\.");
    exibeQuadro("[lf0]");
    exibeQuadro("d[ai]");
    exibeQuadro("a [fn1]");
    exibeQuadro("[il][ap]");
    exibeQuadro("[j-o]");
    exibeQuadro("[4-6AW]");
    exibeQuadro("[^ a-z0-9.]");
    exibeQuadro("\\d");
    exibeQuadro("\\W");
    exibeQuadro("\\p{Punct}");
    exibeQuadro("[\\w&&[^A-Za-z]]");
    exibeQuadro(".o");
    exibeQuadro("no?");
    exibeQuadro("[a-z]*d");
    exibeQuadro("i[a-z]+");
    exibeQuadro("\\s\\d{2}");
    exibeQuadro("\\s[a-z]{2,3}\\s");
    exibeQuadro("[A-Z][a-z]{2,}");
    exibeQuadro("^\\w");
    exibeQuadro("\\d\\W$");
    exibeQuadro("dia\\b");
    exibeQuadro("\\bdia\\b");
  }
}

Ocorrências de o

Regex: o
A Wikipédia foi lançada no dia 15.01.01.
             ↑           ↑
Sequência Início    Fim
o         13        14
o         25        26

Ocorrências de dia

Regex: dia
A Wikipédia foi lançada no dia 15.01.01.
        ↑↑↑                ↑↑↑
Sequência Início    Fim
dia       8         11
dia       27        30

Ocorrências de . — Escape

Metacaracteres como . precisam ser antecedidos \\ para manterem seu valor literal.

Lista de metacaracteres: <>()[]{}\^-=$!|?*+..

Regex: \.
A Wikipédia foi lançada no dia 15.01.01.
                                 ↑  ↑  ↑
Sequência Início    Fim
.         33        34
.         36        37
.         39        40

Ocorrências de l, f e 0 — Classe de caracteres simples

O par [ e ] denota uma classe de caracteres simples.

Cada um dos caracteres contidos na classe são buscados independentemente na entrada.

Regex: [lf0]
A Wikipédia foi lançada no dia 15.01.01.
            ↑   ↑                 ↑  ↑
Sequência Início    Fim
f         12        13
l         16        17
0         34        35
0         37        38

Ocorrências de da e di — Classe de caracteres simples

Caracteres ao lado de uma classe (de caracteres) geram combinações entre si e cada um dos caracteres da classe.

Regex: d[ai]
A Wikipédia foi lançada no dia 15.01.01.
        ↑↑           ↑↑    ↑↑
Sequência Início    Fim
di        8         10
da        21        23
di        27        29

Ocorrências de ia, ip, la e lp — Classe de caracteres simples

Uma classe ao lado de outra gera combinações entre os caracteres de cada, como um produto cartesiano.

Regex: [il][ap]
A Wikipédia foi lançada no dia 15.01.01.
     ↑↑  ↑↑     ↑↑          ↑↑
Sequência Início    Fim
ip        5         7
ia        9         11
la        16        18
ia        28        30

Ocorrências de a seguido de espaço e (f, n ou 1) — Classe de caracteres simples

Regex: a [fn1]
A Wikipédia foi lançada no dia 15.01.01.
          ↑↑↑         ↑↑↑    ↑↑↑
Sequência Início    Fim
a f       10        13
a n       22        25
a 1       29        32

Ocorrências de j até o — Intervalo

- dentro de uma classe denota um intervalo.

Regex: [j-o]
A Wikipédia foi lançada no dia 15.01.01.
    ↑        ↑  ↑ ↑     ↑↑
Sequência Início    Fim
k         4         5
o         13        14
l         16        17
n         18        19
n         24        25
o         25        26

Ocorrências de 4, 5, 6, A e W — Intervalo

Uma classe pode misturar intervalos e caracteres únicos.

Regex: [4-6AW]
A Wikipédia foi lançada no dia 15.01.01.
↑ ↑                             ↑
Sequência Início    Fim
A         0         1
W         2         3
5         32        33

Ocorrências diferentes de espaço, ., de 0 à 9 e de a até z — Negação

^ em uma classe denota uma negação: todos os caracteres diferentes dos da classe serão buscados.

Regex: [^ a-z0-9.]
A Wikipédia foi lançada no dia 15.01.01.
↑ ↑    ↑           ↑
Sequência Início    Fim
A         0         1
W         2         3
é         7         8
ç         19        20

Ocorrências de 0 à 9 - Classes de caracteres pré-definidas

\d é uma classe de caracteres pré-definida, equivalente à [0-9].

\s representa caracteres de espaço (como quebra de linha e tabulação).

\w são os caracteres alfanuméricos em ASCII [a-zA-Z_0-9].

Regex: \d
A Wikipédia foi lançada no dia 15.01.01.
                               ↑↑ ↑↑ ↑↑
Sequência Início    Fim
1         31        32
5         32        33
0         34        35
1         35        36
0         37        38
1         38        39

Ocorrências diferentes de caracteres alfanuméricos ASCII - Classes de caracteres pré-definidas

\W é a negação de \w, equivale à [^a-zA-Z_0-9] ou [^\w].

\S é a negação de \s e \D de \d.

Regex: \W
A Wikipédia foi lançada no dia 15.01.01.
 ↑     ↑   ↑   ↑   ↑   ↑  ↑   ↑  ↑  ↑  ↑
Sequência Início    Fim
          1         2
é         7         8
          11        12
          15        16
ç         19        20
          23        24
          26        27
          30        31
.         33        34
.         36        37
.         39        40

Ocorrências de pontuações — Classes de caracteres POSIX

\p{Punct} é uma classe de caracteres POSIX que representa !"#$%&'()*+,-./:;><?=@[\]^_`{|}~.

Lista completa disponível no JavaDoc da classe Pattern .

Regex: \p{Punct}
A Wikipédia foi lançada no dia 15.01.01.
                                 ↑  ↑  ↑
Sequência Início    Fim
.         33        34
.         36        37
.         39        40

Ocorrências de caracteres alfanuméricos ASCII que não sejam alfabéticos — Subtração

[\w&&[^A-Za-z]] resulta em subtração de [A-Za-z] da classe [a-zA-Z_0-9] (mesmo que \w) resultando então em [_0-9].

Regex: [\w&&[^A-Za-z]]
A Wikipédia foi lançada no dia 15.01.01.
                               ↑↑ ↑↑ ↑↑
Sequência Início    Fim
1         31        32
5         32        33
0         34        35
1         35        36
0         37        38
1         38        39

Ocorrências de qualquer caractere seguido por o — Classes de caracteres pré-definidas

. representa qualquer caractere exceto nova linha.

Regex: .o
A Wikipédia foi lançada no dia 15.01.01.
            ↑↑          ↑↑
Sequência Início    Fim
fo        12        14
no        24        26

Ocorrências de n seguido ou não de o — Quantificadores

O caractere ou classe antecedendo ? é buscado uma ou nenhuma vez.

Regex: no?
A Wikipédia foi lançada no dia 15.01.01.
                  ↑     ↑↑
Sequência Início    Fim
n         18        19
no        24        26

Ocorrências terminadas em d antecedidas opcionalmente por letras minúsculas ASCII — Quantificadores

O caractere ou classe antecedendo * é buscado zero ou mais vezes.

Regex: [a-z]*d
A Wikipédia foi lançada no dia 15.01.01.
        ↑           ↑↑     ↑
Sequência Início    Fim
d         8         9
ad        20        22
d         27        28

Ocorrências de i seguidas por uma ou mais letras minúsculas ASCII — Quantificadores

O caractere ou classe antecedendo + é buscado uma ou mais vezes.

Regex: i[a-z]+
A Wikipédia foi lançada no dia 15.01.01.
   ↑↑↑↑  ↑↑                 ↑↑
Sequência Início    Fim
ikip      3         7
ia        9         11
ia        28        30

Ocorrências de espaço seguidas por dois dígitos — Quantificadores

O caractere ou classe antecedendo {2} é buscado exatamente 2 vezes em sequência.

Regex: \s\d{2}
A Wikipédia foi lançada no dia 15.01.01.
                              ↑↑↑
Sequência Início    Fim
 15       30        33

Ocorrências de espaço seguidas por por duas ou três letras minúsculas ASCII e terminadas em espaço — Quantificadores

O caractere ou classe antecedendo {2,3} é buscado 2 ou 3 vezes em sequência.

Regex: \s[a-z]{2,3}\s
A Wikipédia foi lançada no dia 15.01.01.
           ↑↑↑↑↑       ↑↑↑↑
Sequência Início    Fim
 foi      11        16
 no       23        27

Ocorrências de letra maiúscula ASCII seguidas por por duas ou mais letras minúsculas ASCII — Quantificadores

O caractere ou classe antecedendo {2,} é buscado ao menos 2 vezes em sequência.

Regex: [A-Z][a-z]{2,}
A Wikipédia foi lançada no dia 15.01.01.
  ↑↑↑↑↑
Sequência Início    Fim
Wikip     2         7

Ocorrência de alfanumérico ASCII no ínicio da linha — Fronteiras

^ indica o ínicio de uma linha na entrada.

Caso a entrada tenha apenas uma linha no máximo uma correspondência poderá existir.

Regex: ^\w
A Wikipédia foi lançada no dia 15.01.01.
Sequência Início    Fim
A         0         1

Ocorrência de dígito seguido por caractere não alfanumérico ASCII no fim da linha — Fronteiras

$ indica o fim de uma linha na entrada.

Caso a entrada tenha apenas uma linha no máximo uma correspondência poderá existir.

Regex: \d\W$
A Wikipédia foi lançada no dia 15.01.01.
                                      ↑↑
Sequência Início    Fim
1.        38        40

Ocorrência de palavra terminada em dia — Fronteiras

\b indica um dos limites da palavra (ínicio ou fim).

Regex: dia\b
A Wikipédia foi lançada no dia 15.01.01.
        ↑↑↑                ↑↑↑
Sequência Início    Fim
dia       8         11
dia       27        30

Ocorrência da palavra dia — Fronteiras

Regex: \bdia\b
A Wikipédia foi lançada no dia 15.01.01.
                           ↑↑↑
Sequência Início    Fim
dia       27        30

Verificar se a entrada inteira corresponde à expressão regular

  1. Invoque Pattern#matcher com a expressão regular e a entrada como argumentos.
  2. O método retornará true caso a entrada inteira corresponda ao padrão.
package dev.caiosantesso.regex;

import java.util.regex.Pattern;

public class CorrespondenciaCompleta {
  public static void main(String[] args) {
    String entrada = "Caio";
    String regex = "^[A-Z][a-z]+$";

    boolean b = Pattern.matches(regex, entrada);
    System.out.printf("%s corresponde ao regex? %b", entrada, b);
    //Caio corresponde ao regex? true
  }
}

Manter o resultado de uma correspondência após próximo Matcher#find

Expressão regular ignorando caixa das letras

  1. Some as constantes Pattern.UNICODE_CASE e Pattern.CASE_INSENSITIVE.
  2. Informe a soma no segundo argumento de Pattern#compile.
package dev.caiosantesso.regex;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MaiusculasEMinusculasUnicode {

  public static void main(String[] args) {
    String entrada = "AÇÚCAR açÃo";
    String regex = "[çúãa]";

    int flags = Pattern.UNICODE_CASE + Pattern.CASE_INSENSITIVE;
    Pattern padrao = Pattern.compile(regex, flags);
    Matcher matcher = padrao.matcher(entrada);

    while (matcher.find())
      System.out.printf("%s ", matcher.group());
    //A Ç Ú A a ç Ã
  }
}

Expressão regular com classes de caracteres Unicode

  1. Chame Pattern#compile passando a constante Pattern.UNICODE_CHARACTER_CLASS no segundo parâmetro.
package dev.caiosantesso.regex;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ClassesDeCaractereUnicode {

  public static void main(String[] args) {
    String entrada = "açaí";
    String regex = "\\w";

    Pattern padraoUnicode =
        Pattern.compile(regex, Pattern.UNICODE_CHARACTER_CLASS);
    Matcher matcher = padraoUnicode.matcher(entrada);

    while (matcher.find())
      System.out.printf("%s ", matcher.group());
    // a ç a í
  }
}

Expressão regular aplicada em cada linha da entrada

  1. Chame Pattern#compile enviando a constante Pattern.MULTILINE como segundo argumento.
package dev.caiosantesso.regex;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MultiLinhas {

  public static void main(String[] args) {
    String entradaComDuasLinhas = "Uma frase;\nOutra frase;";
    String regex = "^[A-Z].*;$";

    Pattern padrao = Pattern.compile(regex, Pattern.MULTILINE);
    Matcher matcher = padrao.matcher(entradaComDuasLinhas);

    while (matcher.find())
      System.out.printf("%s\n", matcher.group());
    //Uma frase;
    //Outra frase;
  }
}

Expressão regular com metacaracteres interpretados literalmente

  1. Informe a expressão regular no método Pattern#quote().
  2. Utilize a String devolvida como expressão regular normalmente.
package dev.caiosantesso.regex;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class PadraoLiteral {
  public static void main(String[] args) {
    String regexLiteral = Pattern.quote("[a-z]");

    Pattern padrao = Pattern.compile(regexLiteral);
    Matcher matcher = padrao.matcher("--[a-z]--");
    System.out.println(matcher.find() + " " + matcher.group());
    //true
  }
}

Divisão de strings como vetor

  1. Crie um Pattern como usual.
  2. Chame split() na referência devolvida, qualquer implementação de CharSequence pode ser enviada como argumento.
  3. Cada string ao redor das correspondências será armazenada no vetor de String retornado por split().
    1. Caso não haja uma string ao redor da correspondência, uma string vazia é devolvida.
    2. ⚠️ Strings vazias nos últimos índices do vetor são descartadas.
  4. Caso não haja nenhuma correspondência, split() devolve o argumento inteiro em um vetor de uma posição.
package dev.caiosantesso.regex;

import java.util.Arrays;
import java.util.regex.Pattern;

public class DividirStringsEmVetor {
  public static void main(String[] args) {
    Pattern padrao = Pattern.compile(";");

    String[] letras = padrao.split(new StringBuilder(";A;B;;C;;"));
    System.out.println(Arrays.toString(letras));
    //[, A, B, , C]

    String[] frase = padrao.split(new StringBuilder("ABC"));
    System.out.println(frase.length);
    //1
  }
}

Divisão de strings como stream

  1. Crie um Pattern como usual.
  2. Chame splitAsStream() na referência devolvida, qualquer implementação de CharSequence pode ser enviada como argumento.
  3. Cada string ao redor das correspondências é armazenada no Stream<String> retornado por splitAsStream().
    1. Caso não haja uma string ao redor da correspondência, uma string vazia é devolvida.
    2. ⚠️ Strings vazias após a última não vazia são descartadas.
  4. Caso não haja nenhuma correspondência, o argumento é devolvido inteiro, em uma stream com um elemento.
package dev.caiosantesso.regex;

import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class DividirStringEmStream {

  public static void main(String[] args) {
    String entrada = ".A.B..C..";

    List<String> pedacos = Pattern.compile("\\.")
                                  .splitAsStream(entrada)
                                  .collect(Collectors.toList());
    System.out.println(pedacos);
    // [, A, B, C]

    Long entradaInteira = Pattern.compile("\\d")
                                 .splitAsStream(entrada)
                                 .count();
    System.out.println(entradaInteira);
    // 1
  }
}

Matcher#find como Predicate: remover de stream elementos sem correspondências

  1. Crie um Pattern.
  2. Chame asPredicate() na referência obtida, um Predicate<String> será devolvido.
    1. Esse Predicate é equivalente à elemento -> pattern.matcher(elemento).find();
  3. Use então o Predicate em filter() de um Stream<String>.
    1. Todas as Strings que não tenham ao menos uma correspondência à expressão regular serão removidas.
package dev.caiosantesso.regex;

import java.util.List;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import java.util.stream.Stream;

import static java.util.stream.Collectors.toList;

public class RemoverItensSemOcorrencia {
  public static void main(String[] args) {
    Pattern padrao = Pattern.compile("\\d");
    Predicate<String> contendoDigito = padrao.asPredicate();

    List<String> lista = Stream.of("A1", "B", " ", "D4")
                          .filter(contendoDigito)
                          .collect(toList());

    System.out.println(lista); // [A1, D4]
  }
}

Matcher#matches como Predicate: remover de stream elementos não correpondentes

  1. Crie um Pattern.
  2. Chame asMatchPredicate() na referência obtida, um Predicate<String> será devolvido.
    1. Esse Predicate é equivalente à elemento -> pattern.matcher(elemento).matches();
  3. Use então o Predicate em filter() de um Stream<String>.
    1. Todas as strings que não correspondam completamente à expressão regular serão removidas.
package dev.caiosantesso.regex;

import java.util.List;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import java.util.stream.Stream;

import static java.util.stream.Collectors.toList;

public class RemoverItensNaoCorrespondentes {
  public static void main(String[] args) {
    Pattern p = Pattern.compile("^[A-Z].*");
    Predicate<String> comecandoComMaiuscula = p.asMatchPredicate();

    List<String> lista = Stream.of("A", "b", "c", "Dd")
                               .filter(comecandoComMaiuscula)
                               .collect(toList());

    System.out.println(lista); // [A, Dd]
  }
}

Stream de correspondências

  1. Crie um Matcher.
  2. Chame results() no objeto criado para obter uma stream de MatchResult.
  3. Cada MatchResult da stream representa uma correspondência da expressão regular.
    1. A string pode ser acessada com MatchResult#group;
    2. Bem como a posição de ínicio e fim com MatchResult#start e MatchResult#end.
package dev.caiosantesso.regex;

import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class CorrespondenciasComoStream {

  public static void main(String[] args) {
    String entrada = "a5bc32";
    String digitos = "\\d";

    Matcher matcher = Pattern.compile(digitos)
                             .matcher(entrada);
    matcher.results()
           .map(MatchResult::group)
           .forEach(System.out::print); // 532
  }
}

String com correspondências substituídas por literal

  1. Crie um Matcher.
  2. Invoque replaceAll() com a string que substuirá as correspondências da entrada.
  3. O retorno do método conterá então a string com as correspondências substituídas.
package dev.caiosantesso.regex;

import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class SubstituirCorrespondencias {

  public static void main(String[] args) {
    String e = Map.of("char", Character.SIZE, "short", Short.SIZE)
                  .toString();

    Matcher matcher = Pattern.compile("=")
                             .matcher(e);
    String resultado = matcher.replaceAll(" -> ");

    System.out.println(resultado); // {short -> 16, char -> 16}
  }
}

String com correspondências substituídas por barra invertida ou cifrão

  1. Invoque Matcher#quoteReplacement enviando string com barra invertida e/ou cifrão.
  2. Então use a string devolvida em replaceAll().
package dev.caiosantesso.regex;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class SubstituirCorrespondenciasComBarraInvertida {

  public static void main(String[] args) {
    String diretorio = "C:/Users/eu";

    Matcher matcher = Pattern.compile("/")
                             .matcher(diretorio);

    String substituto = Matcher.quoteReplacement("\\");
    String resultado = matcher.replaceAll(substituto);
    System.out.println(resultado); // C:\Users\eu
  }
}

String com algumas correspondências substituídas por literal

  1. Crie um Matcher.
  2. Chame find() para tentar encontrar uma correspondência.
  3. Invoque appendReplacement() com um StringBuilder e uma string como argumentos.
    1. StringBuilder receberá todos caracteres entre a última correspondência de find() (exclusive) até o caratere substituído (inclusive).
    2. A string do segundo argumento substituirá as correspondências.
  4. Itere as duas chamadas de método à gosto.
  5. Opcionalmente execute appendTail() para inserir os caracteres restantes no StringBuilder enviado como seu argumento.
package dev.caiosantesso.regex;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class SubstituirAlgumasCorrespondencias {

  public static void main(String[] args) {
    String entrada = "Ryzen,5900X,3379,90";
    StringBuilder resultado = new StringBuilder();

    Pattern p = Pattern.compile(",");
    Matcher m = p.matcher(entrada);

    int i = 0;
    while (m.find() && i++ < 2) {
      resultado.append(i)
               .append("_");
      m.appendReplacement(resultado, " : ");
    }
    System.out.println(resultado); // 1_Ryzen : 2_5900X :

    m.appendTail(resultado);
    System.out.println(resultado); // 1_Ryzen : 2_5900X : 3379,90
  }
}

String com correspondências substituídas por função

  1. Crie um Matcher.
  2. Chame replaceAll() com uma lambda de tipo Function<MatchResult, String> como argumento.
  3. Cada correspondência é enviada como argumento do tipo MatchResult e é substituída pela String resultante da função.
  4. O retorno de replaceAll() então será uma string com as substituições realizadas.
package dev.caiosantesso.regex;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class SubstituirCorrespondenciasComFuncao {

  public static void main(String[] args) {
    String entrada = "deve_ser_igual_a_seis";

    Matcher matcher = Pattern.compile("_.").matcher(entrada);
    String resultado = matcher.replaceAll(c -> c.group()
                                                .substring(1)
                                                .toUpperCase());

    System.out.println(resultado); //deveSerIgualASeis
  }
}

Referências

Escrito por Caio Santesso.

Comentários

  • Conteúdo dos posts, exceto onde indicado contrário, licenciado sob a licença CC BY-SA 4.0 .