W3docs

Введение в регулярные выражения Java

Введение в регулярные выражения Java с пакетом java.util.regex: Pattern, Matcher и основной синтаксис.

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

Что такое регулярное выражение

Regex — это просто строка, написанная с использованием специального синтаксиса, но Java не интерпретирует её посимвольно каждый раз. Вместо этого шаблон компилируется один раз в объект Pattern, а затем применяется к входным данным через Matcher. Скомпилированная форма представляет собой эффективный конечный автомат, поэтому повторное использование одного Pattern для многих входных данных гораздо дешевле повторной компиляции.

Шаблоны описывают структуру: литерал cat соответствует именно этим буквам, а метасимволы описывают формы — \d означает любую цифру, + — «одно или несколько», . — «любой символ». Комбинируя их, вы можете описать номера телефонов, адреса электронной почты или строки журнала в одной строке кода.

import java.util.regex.Pattern;

public class FirstPattern {
    public static void main(String[] args) {
        // Compile the pattern once; reuse the result.
        Pattern digits = Pattern.compile("\\d+");
        System.out.println(digits.matcher("abc123").find()); // true
        System.out.println(digits.matcher("hello").find());  // false
    }
}

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

Pattern и Matcher

Почти всю работу выполняют два класса. Pattern — это скомпилированный, многократно используемый, потокобезопасный шаблон. Matcher — это состоятельный движок, запускающий этот шаблон против конкретного входного значения: он отслеживает текущую позицию в тексте, какие группы захвачены и где находилось последнее совпадение. Создавайте новый Matcher для каждого входного значения; никогда не используйте один совместно в нескольких потоках.

ТипРоль
PatternСкомпилированный шаблон. Неизменяемый, потокобезопасный, многократно используемый.
MatcherПрименяет Pattern к одному входному значению. Хранит состояние совпадения.
Pattern.compile(regex)Создаёт Pattern из строки regex.
pattern.matcher(input)Возвращает Matcher, привязанный к этому входному значению.
String.matches(regex)Вспомогательный метод одноразового использования, компилирующий и полностью сопоставляющий за один вызов.
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class PatternAndMatcher {
    public static void main(String[] args) {
        Pattern p = Pattern.compile("\\w+@\\w+\\.\\w+");
        Matcher m = p.matcher("ping me at [email protected] please");
        if (m.find()) {
            System.out.println("Found email: " + m.group());
        }
    }
}

find() против matches()

Самая распространённая ошибка новичков — путаница между двумя способами запуска шаблона. matches() требует, чтобы всё входное значение совпадало с шаблоном от начала до конца. find() сканирует любую подстроку, которая совпадает, и может вызываться многократно для обхода всех вхождений. lookingAt() находится между ними: он привязывается к началу, но не требует совпадения до конца.

МетодПривязан к началу?Должен совпасть до конца?Повторяемый?
matches()даданет
lookingAt()данетнет
find()нетнетда
import java.util.regex.Pattern;

public class FindVsMatches {
    public static void main(String[] args) {
        Pattern p = Pattern.compile("\\d+");
        System.out.println(p.matcher("42").matches());        // true  (whole input)
        System.out.println(p.matcher("age 42").matches());    // false (extra text)
        System.out.println(p.matcher("age 42").find());       // true  (substring)
        System.out.println(p.matcher("age 42").lookingAt());  // false (no digit at start)
    }
}

Общий синтаксис для построения шаблонов

Большинство реальных шаблонов собираются из небольшого набора строительных блоков: классов символов, предопределённых сокращений, квантификаторов и якорей. Знание этих элементов охватывает большую часть задач. Каждая конструкция рассматривается в отдельной главе — см. Синтаксис regex, классы символов и квантификаторы для получения полной информации.

КонструкцияЗначениеПример
.Любой одиночный символ (кроме символа новой строки)a.c совпадает с abc, axc
\d \w \sЦифра, символ слова, пробельный символ\d\d совпадает с 42
[abc]Любой из символов a, b, c[aeiou] совпадает с гласной
[^abc]Любой символ кроме a, b, c[^0-9] совпадает с нецифровым символом
* + ?Ноль и более, один и более, ноль или одинab+ совпадает с ab, abb
{n} {n,m}Ровно n, от n до m\d{3} совпадает с 555
^ $Начало, конец ввода/строки^Hi совпадает с начальным Hi
(...)Захватывающая группа(\d{4}) захватывает четыре цифры
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class GroupsExample {
    public static void main(String[] args) {
        // Two capturing groups: year and month.
        Pattern date = Pattern.compile("(\\d{4})-(\\d{2})");
        Matcher m = date.matcher("Released 2025-11 to users");
        if (m.find()) {
            System.out.println("Full: " + m.group(0)); // 2025-11
            System.out.println("Year: " + m.group(1)); // 2025
            System.out.println("Month: " + m.group(2)); // 11
        }
    }
}

Практический пример

Программа ниже компилирует один шаблон номера телефона и демонстрирует весь API на его основе: она обходит каждое совпадение с помощью find(), считывает захватывающие группы и позиции совпадений, сравнивает find() с matches() и перезаписывает текст с помощью replaceAll(). Запустите её, чтобы увидеть движок в действии.

java— editable, runs on the server

Что следует вынести из результатов:

  • find() вызывается в цикле и возвращает два совпадения, поэтому один и тот же Matcher обходит текст по одному вхождению за раз, пока не вернёт false.
  • group(1) и group(2) возвращают части в скобках (555 и 1234), а group() без аргумента возвращает всё совпадение целиком.
  • start() и end() возвращают смещения символов каждого совпадения, что позволяет выделить или вырезать нужную часть исходного текста.
  • matches() на полном предложении выводит false, потому что шаблон не охватывает всю строку, тогда как "555-1234" отдельно выводит true — подтверждение того, что matches() работает только с полным входным значением.
  • replaceAll("XXX-XXXX") перезаписывает каждое совпадение за один проход, создавая маскированное предложение и показывая, как шаблоны управляют преобразованием текста.

Что дальше

Теперь, когда вы знаете ключевые компоненты — Pattern, Matcher и разницу между find() и matches() — углубитесь в тематические главы:

  • Pattern и Matcher — полный API для компиляции и запуска шаблонов.
  • Синтаксис regex — все метасимволы и экранирующие последовательности с объяснениями.
  • Классы символов — наборы, диапазоны и отрицание.
  • Квантификаторы — жадное, ленивое и притяжательное повторение.
  • Захватывающие группы — извлечение и обратные ссылки на части совпадений.
  • Флаги — нечувствительность к регистру, многострочный режим и другие модификаторы.

Практика

Практика
В чём ключевое различие между Matcher.matches() и Matcher.find()?
В чём ключевое различие между Matcher.matches() и Matcher.find()?
Was this page helpful?