Регулярные выражения в Java с примерами: на практике

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Регулярные выражения в Java: от теории к практике

Регулярные выражения (regex) — мощный инструмент для поиска, замены и валидации текста. В Java работа с ними реализована через пакет java.util.regex, который включает два основных класса: Pattern (шаблон) и Matcher (сопоставитель). В этой статье мы разберём синтаксис, ключевые методы и закрепим знания на реальных примерах кода.

Материал будет полезен как новичкам, только знакомящимся с Java, так и опытным разработчикам, желающим освежить знания. Все примеры можно сразу запускать в вашей IDE.

1. Основы работы с Pattern и Matcher

Любая работа с regex в Java начинается с компиляции шаблона через Pattern.compile(). После этого создаётся объект Matcher, который применяет шаблон к строке.

Рассмотрим простейший пример: поиск всех цифр в тексте.

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

public class RegexDemo {
    public static void main(String[] args) {
        String text = "Java версия 21 вышла в 2023 году";
        String regex = "\\d+"; // одна или более цифр

        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(text);

        while (matcher.find()) {
            System.out.println("Найдено: " + matcher.group());
        }
    }
}

Вывод программы:

Найдено: 21
Найдено: 2023

Обратите внимание на двойной слеш \\d — в Java строковый литерал требует экранирования обратной косой черты. Если в regex нужно указать \d, в коде пишем \\d.

2. Синтаксис регулярных выражений: метасимволы и квантификаторы

Чтобы эффективно использовать regex, важно запомнить основные метасимволы:

  • . — любой символ (кроме перевода строки);
  • \\d — цифра (аналог [0-9]);
  • \\w — буква, цифра или подчёркивание ([a-zA-Z0-9_]);
  • \\s — пробельный символ;
  • ^ — начало строки;
  • $ — конец строки.

Квантификаторы управляют количеством повторений:

  • + — один и более раз;
  • * — ноль и более раз;
  • ? — ноль или один раз;
  • {n} — ровно n раз;
  • {n,m} — от n до m раз.

Пример: найдём все слова, состоящие только из латинских букв, длиной от 3 до 5 символов.

String text = "Java regex example for beginners";
String regex = "\\b[a-zA-Z]{3,5}\\b";

Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(text);

while (matcher.find()) {
    System.out.println(matcher.group());
}
// Вывод: Java, regex, for

Граница слова \\b предотвращает частичное совпадение (например, "Java" не будет частью "JavaScript").

3. Практические примеры: валидация и извлечение данных

Перейдём к задачам, которые часто встречаются в реальной разработке.

3.1. Валидация email-адреса

Простейшая проверка: наличие символа "@" и домена.

public static boolean isValidEmail(String email) {
    String regex = "^[\\w.-]+@[\\w.-]+\\.\\w{2,}$";
    return Pattern.matches(regex, email);
}

public static void main(String[] args) {
    System.out.println(isValidEmail("user@example.com")); // true
    System.out.println(isValidEmail("invalid-email"));    // false
}

Метод Pattern.matches() автоматически проверяет строку целиком (эквивалентно matcher.matches()).

3.2. Извлечение номеров телефонов

Допустим, в тексте встречаются номера в формате "+7 (999) 123-45-67".

String text = "Контакт: +7 (495) 123-45-67, резервный: +7 (999) 987-65-43";
String regex = "\\+7\\s?\\(\\d{3}\\)\\s?\\d{3}-\\d{2}-\\d{2}";

Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(text);

while (matcher.find()) {
    System.out.println("Телефон: " + matcher.group());
}
// Вывод:
// Телефон: +7 (495) 123-45-67
// Телефон: +7 (999) 987-65-43

3.3. Замена текста по шаблону

Класс Matcher поддерживает замену с помощью replaceAll(). Заменим все цифры на звёздочки:

String text = "Пароль: 12345, код: 6789";
String result = text.replaceAll("\\d", "*");
System.out.println(result);
// Вывод: Пароль: *****, код: ****

4. Продвинутые возможности: группы и флаги

Группы позволяют извлекать части совпадения. Например, разберём строку с датой "2023-12-25" на год, месяц и день.

String date = "Сегодня 2023-12-25";
String regex = "(\\d{4})-(\\d{2})-(\\d{2})";

Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(date);

if (matcher.find()) {
    System.out.println("Год: " + matcher.group(1));   // 2023
    System.out.println("Месяц: " + matcher.group(2)); // 12
    System.out.println("День: " + matcher.group(3));  // 25
}

Флаги изменяют поведение поиска. Например, Pattern.CASE_INSENSITIVE игнорирует регистр:

Pattern pattern = Pattern.compile("java", Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher("Java JAVA java");
while (matcher.find()) {
    System.out.print(matcher.group() + " "); // Java JAVA java
}

Полезный флаг Pattern.MULTILINE заставляет якор

Блоги

Рекомендаций по книгам