Atualizado: 26/07/2025

Este conteúdo é original e não foi gerado por inteligência artificial.

Expressões Regulares (Regex) em Java

Expressões regulares (Regex) são padrões que descrevem um conjunto de strings. Elas são uma ferramenta extremamente poderosa para validação, busca, extração e manipulação de texto de forma avançada. Antes de mergulhar no código Java, é crucial entender os blocos que formam uma expressão regular.

Os Blocos de Construção das Expressões Regulares

Toda Regex é construída a partir de uma combinação de caracteres literais e metacaracteres.

ComponenteSímbolos ComunsDescriçãoExemplo
Caracteres Literaisa, B, 1, !Qualquer caractere sem significado especial. Ele corresponde a si mesmo.gato corresponde a "gato"
Metacaracteres\d, \w, \s, .Atalhos para conjuntos comuns de caracteres.

- \d: Qualquer dígito (0-9).

- \w: Qualquer caractere de palavra (a-z, A-Z, 0-9, _).

- \s: Qualquer caractere de espaço em branco.

- .: Qualquer caractere (exceto nova linha).
\d\d corresponde a "25"
Quantificadores*, +, ?, {n}Controlam quantas vezes o elemento anterior pode aparecer.

- *: Zero ou mais vezes.

- +: Uma ou mais vezes.

- ?: Zero ou uma vez (opcional).

- {n}: Exatamente n vezes.
\d{3} corresponde a "123"
Classes de Caracteres[abc], [a-z]Correspondem a um único caractere de um conjunto definido.

- [abc]: Corresponde a 'a', 'b', ou 'c'.

- [a-z]: Corresponde a qualquer letra minúscula.
gr[ae]y corresponde a "gray" e "grey"
Grupos de Captura(...)Agrupam partes do padrão. São essenciais para extrair subconjuntos específicos do texto que correspondeu.(\d{2}) captura os dois dígitos
Âncoras^, $Indicam posições.

- ^: Início da string.

- $: Fim da string.
^Fim corresponde a "Fim" apenas no início da string.

Lembre-se: em uma String Java, a barra invertida \ é um caractere especial. Portanto, para que o motor Regex veja um metacaractere como \d, você precisa escrevê-lo no código como "\\d".

Como Usar Regex em Java

Existem duas abordagens principais para trabalhar com Regex em Java.

Abordagem 1: Métodos Convenientes da Classe String

Para tarefas simples e pontuais, a própria classe String oferece métodos que utilizam expressões regulares internamente.

matches()

Este método retorna true somente se a string inteira corresponder exatamente à expressão regular.

String input = "+12343454556";
// Verifica um '+' opcional no início, seguido por exatamente 11 dígitos.
boolean result = input.matches("\\+?\\d{11}");

if (result) {
    System.out.println("É um formato de telefone válido.");
}

split()

Este método divide uma string em um array com base em um delimitador definido por uma Regex.

String text = "FIFA will never regret it, not even for a second.";
// O regex divide a string por um ou mais espaços, vírgulas ou pontos.
String[] words = text.split("[\\s,.]+");

for (String word : words) {
    System.out.println(word);
}

O resultado será:

FIFA
will
never
regret
it
not
even
for
a
second

Abordagem 2: Controle Total com Pattern e Matcher

Para controle completo, maior performance em operações repetitivas e funcionalidades avançadas, o Java oferece o pacote java.util.regex.

  • Pattern: Representa a expressão regular de forma compilada e otimizada. Compile uma vez, reutilize várias vezes.
  • Matcher: O "motor" que executa as operações de busca em uma string de entrada, utilizando um Pattern compilado.

O fluxo de regex é:

  1. Compilar o Regex: Crie um objeto Pattern com Pattern.compile("seu_regex").
  2. Criar o Matcher: Obtenha um objeto Matcher com pattern.matcher("string_de_entrada").
  3. Executar a Busca: Utilize métodos como find() para encontrar correspondências.

Encontrando Todas as Ocorrências

Este é o uso mais comum e poderoso do Matcher.

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

public class RegexApp {
    public static void main(String[] args) {
        String input = "Hello Java! Hello JavaScript! JavaSE 8.";
        Pattern pattern = Pattern.compile("Java(\\w*)");
        Matcher matcher = pattern.matcher(input);

        // O laço while(matcher.find()) é a forma canônica de iterar por todas as correspondências.
        while (matcher.find()) {
            System.out.println("Correspondência: " + matcher.group(0) + " | Grupo: " + matcher.group(1));
        }
    }
}

Resultado:

Correspondência: Java | Grupo:
Correspondência: JavaScript | Grupo: Script
Correspondência: JavaSE | Grupo: SE

O método matcher.group() (ou group(0)) retorna a correspondência inteira. matcher.group(1) retorna o texto capturado pelo primeiro par de parênteses (...) no regex.

Modificadores de Modo (Flags)

Agora que conhecemos o Pattern, podemos explorar como modificar seu comportamento. A necessidade mais comum é fazer uma busca que ignore maiúsculas e minúsculas (case-insensitive). Existem duas maneiras de fazer isso:

1. Usando um Marcador Inline (?i): Você pode inserir o marcador (?i) diretamente no início da sua expressão regular.

// O (?i) faz com que "java" corresponda a "Java", "java", "JAVA", etc.
Pattern patternCI = Pattern.compile("(?i)java(\\w*)");
Matcher matcherCI = patternCI.matcher("Hello java! Hello JAVA!");
while (matcherCI.find()) {
    System.out.println("Encontrado: " + matcherCI.group());
}

2. Usando uma Flag no Método compile(): A forma mais comum e recomendada de fazer isso é passar um segundo argumento para o método compile().

// O segundo argumento Pattern.CASE_INSENSITIVE ativa o modo case-insensitive.
Pattern patternFlag = Pattern.compile("java(\\w*)", Pattern.CASE_INSENSITIVE);
Matcher matcherFlag = patternFlag.matcher("Hello java! Hello JAVA!");
while (matcherFlag.find()) {
    System.out.println("Encontrado: " + matcherFlag.group());
}

Ambas as formas produzem o mesmo resultado. A segunda abordagem é frequentemente preferida por ser mais explícita e legível no código Java.

Quando Usar Cada Abordagem?

  • Use os métodos da classe String (matches, split) quando:

    • A operação é simples e realizada apenas uma vez (não está em um loop).
    • A simplicidade do código é mais importante que a performance.
  • Use Pattern e Matcher quando:

    • O mesmo padrão de Regex precisa ser aplicado várias vezes (dentro de um loop). Compilar o Pattern uma vez é muito mais eficiente.
    • Você precisa de funcionalidades avançadas, como encontrar múltiplas ocorrências (find()), capturar grupos específicos (group(n)) ou obter os índices de uma correspondência.

Para uma lista exaustiva de todas as construções de Regex suportadas pela implementação Java, a documentação oficial da classe Pattern é a referência definitiva.

📝 Exercícios

Tarefa 1: Validar um CEP

Descrição: Complete o método validarCep para que ele retorne true se a string de entrada corresponder exatamente ao formato de CEP brasileiro (XXXXX-XXX), e false caso contrário.

Código inicial:

public class Main {
    public static void main(String[] args) {
        System.out.println("Testando '01001-000': " + validarCep("01001-000")); // Deve retornar true
        System.out.println("Testando '99999-999': " + validarCep("99999-999")); // Deve retornar true
        System.out.println("Testando '12345-abc': " + validarCep("12345-abc")); // Deve retornar false
        System.out.println("Testando '1234-5678': " + validarCep("1234-5678")); // Deve retornar false
    }

    static boolean validarCep(String cep) {
        // Use o método String.matches() com a expressão regular apropriada.
        // O regex deve exigir 5 dígitos, um hífen, e depois 3 dígitos.

    }
}
Resposta

Solução:

public class Main {
    public static void main(String[] args) {
        System.out.println("Testando '01001-000': " + validarCep("01001-000")); // Deve retornar true
        System.out.println("Testando '99999-999': " + validarCep("99999-999")); // Deve retornar true
        System.out.println("Testando '12345-abc': " + validarCep("12345-abc")); // Deve retornar false
        System.out.println("Testando '1234-5678': " + validarCep("1234-5678")); // Deve retornar false
    }

    static boolean validarCep(String cep) {
        return cep.matches("\\d{5}-\\d{3}");
    }
}

Explicação: A expressão regular \\d{5}-\\d{3} é ideal para esta validação:

  • \\d{5}: Corresponde a exatamente 5 ocorrências de um dígito (\d).
  • -: Corresponde ao caractere literal de hífen.
  • \\d{3}: Corresponde a exatamente 3 ocorrências de um dígito. O método matches() garante que a string inteira obedeça a este padrão.
  • Tarefa 2: Dividir uma Lista de Tags

    Descrição: Você recebeu uma string contendo várias tags separadas por vírgula e espaços. Use o método String.split() para dividir a string em um array de tags individuais, removendo os delimitadores.

    Código inicial:

    public class Main {
        public static void main(String[] args) {
            String listaDeTags = "java, regex, programação, desenvolvimento";
            String[] tags = null;
    
            // Use o método split para preencher o array "tags".
            // O delimitador pode ser uma vírgula seguida por espaços opcionais.
    
    
            // Este loop irá imprimir cada tag do array.
            for (String tag : tags) {
                System.out.println("Tag: " + tag);
            }
        }
    }
    Resposta

    Solução:

    public class Main {
        public static void main(String[] args) {
            String listaDeTags = "java, regex, programação, desenvolvimento";
    
            // O regex ",\\s*" divide pela vírgula seguida por zero ou mais espaços.
            String[] tags = listaDeTags.split(",\\s*");
    
            for (String tag : tags) {
                System.out.println("Tag: " + tag);
            }
        }
    }

    Explicação: O método split() usa a expressão regular fornecida como delimitador.

  • ,: Corresponde ao caractere literal de vírgula.
  • \\s*: Corresponde a zero ou mais (*) ocorrências de um caractere de espaço em branco (\s). Isso garante que a divisão funcione tanto para "java,regex" quanto para "java, regex", resultando em um array limpo.
  • Tarefa 3: Encontrar Todos os Preços em um Texto

    Descrição: Use as classes Pattern e Matcher para encontrar e imprimir todos os valores de preços (no formato R$XX.XX) contidos em um texto.

    Código inicial:

    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    public class Main {
        public static void main(String[] args) {
            String texto = "O produto A custa R$23.50, o produto B custa R$19.99 e a taxa é de R$5.00.";
    
            // Crie o Pattern e o Matcher.
            // O regex deve encontrar "R$" seguido por dígitos, um ponto, e mais dois dígitos.
    
    
            // Use um laço while(matcher.find()) para imprimir todas as correspondências.
            System.out.println("Preços encontrados:");
    
        }
    }
    Resposta

    Solução:

    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    public class Main {
        public static void main(String[] args) {
            String texto = "O produto A custa R$23.50, o produto B custa R$19.99 e a taxa é de R$5.00.";
    
            Pattern pattern = Pattern.compile("R\\$\\d+\\.\\d{2}");
            Matcher matcher = pattern.matcher(texto);
    
            System.out.println("Preços encontrados:");
            while (matcher.find()) {
                System.out.println(matcher.group());
            }
        }
    }

    Explicação: A expressão R\\$\\d+\\.\\d{2} é detalhada assim:

  • R\\$: Corresponde ao literal R$. O $ é um caractere especial em Regex e precisa ser "escapado" com \\.
  • \\d+: Corresponde a uma ou mais (+) ocorrências de um dígito (\d).
  • \\.: Corresponde ao literal .. O . também é especial (significa "qualquer caractere") e precisa ser escapado.
  • \\d{2}: Corresponde a exatamente dois dígitos. O laço while(matcher.find()) é a forma padrão de iterar sobre todas as correspondências em um texto.
  • Tarefa 4: Censurar uma Palavra (Ignorando Maiúsculas/Minúsculas)

    Descrição: Escreva um método que receba um texto e censure todas as ocorrências da palavra "senha", substituindo-a por "**". A censura deve funcionar independentemente se a palavra está em maiúsculas ou minúsculas.

    Código inicial:

    public class Main {
        public static void main(String[] args) {
            String texto = "Por favor, não digite sua Senha aqui. A senha é secreta.";
            String censurado = censurarPalavra(texto);
            System.out.println(censurado); // Resultado: Por favor, não digite sua ****** aqui. A ****** é secreta.
        }
    
        static String censurarPalavra(String texto) {
            // Use o método replaceAll.
            // Dica: para ignorar maiúsculas/minúsculas, inicie a regex com o marcador (?i).
    
        }
    }
    Resposta

    Solução:

    public class Main {
        public static void main(String[] args) {
            String texto = "Por favor, não digite sua Senha aqui. A senha é secreta.";
            String censurado = censurarPalavra(texto);
            System.out.println(censurado);
        }
    
        static String censurarPalavra(String texto) {
            // (?i) é um marcador (flag) que torna a expressão que o segue case-insensitive.
            return texto.replaceAll("(?i)senha", "******");
        }
    }

    Explicação: O método replaceAll() pode usar marcadores (flags) dentro da própria expressão regular.

  • (?i): É um marcador que ativa o modo case-insensitive (ignora maiúsculas/minúsculas) para a expressão que o segue.
  • senha: É o texto a ser encontrado.
  • "******": É o texto que será usado na substituição.
  • Tarefa 5: Extrair o Nome de Usuário de um Email

    Descrição: Complete o método extrairUsuario para que ele retorne apenas a parte do nome de usuário (o que vem antes do @) de um endereço de email, usando um grupo de captura.

    Código inicial:

    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    public class Main {
        public static void main(String[] args) {
            String email = "usuario.exemplo@provedor.com";
            String usuario = extrairUsuario(email);
            System.out.println(usuario); // Resultado esperado: usuario.exemplo
        }
    
        static String extrairUsuario(String email) {
            // Use Pattern, Matcher e um grupo de captura () para extrair
            // a parte do email antes do "@".
    
        }
    }
    Resposta

    Solução:

    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    public class Main {
        public static void main(String[] args) {
            String email = "usuario.exemplo@provedor.com";
            String usuario = extrairUsuario(email);
            System.out.println(usuario);
        }
    
        static String extrairUsuario(String email) {
            // O regex captura um ou mais caracteres de qualquer tipo (.+)
            // em um grupo de captura, antes do símbolo @.
            Pattern pattern = Pattern.compile("(.+)@");
            Matcher matcher = pattern.matcher(email);
    
            if (matcher.find()) {
                // matcher.group(1) retorna o conteúdo capturado pelo primeiro par de parênteses.
                return matcher.group(1);
            }
    
            return "Usuário não encontrado";
        }
    }

    Explicação:

  • (.+): Esta é a parte principal. Os parênteses () criam um grupo de captura. . significa "qualquer caractere" e + significa "um ou mais". Juntos, capturam tudo antes do @.
  • @: Corresponde ao caractere literal @. Quando matcher.find() encontra uma correspondência, matcher.group() (ou matcher.group(0)) retornaria o texto inteiro correspondido ("usuario.exemplo@"). No entanto, matcher.group(1) retorna apenas o texto capturado pelo primeiro grupo, que é exatamente o que queremos.
  • Política de Privacidade

    Copyright © www.programicio.com Todos os direitos reservados

    É proibida a reprodução do conteúdo desta página sem autorização prévia do autor.

    Contato: programicio@gmail.com