Рубрики
Без рубрики

Как подсчитать количество совпадений для регулярного выражения?

Регулярные выражения могут помочь нам в обработке текста. Здесь мы рассмотрим, как подсчитать количество совпадений регулярного выражения в некотором тексте.

Автор оригинала: baeldung.

1. Обзор

Регулярные выражения могут использоваться для различных задач обработки текста, таких как алгоритмы подсчета слов или проверка ввода текста.

В этом уроке мы рассмотрим, как использовать регулярные выражения для подсчета количества совпадений в некотором тексте .

2. Пример использования

Давайте разработаем алгоритм, способный подсчитывать, сколько раз действительное электронное письмо появляется в строке .

Чтобы определить адрес электронной почты, мы будем использовать простой шаблон регулярного выражения:

([a-z0-9_.-]+)@([a-z0-9_.-]+[a-z])

Обратите внимание, что это тривиальный шаблон только для демонстрационных целей, так как фактическое регулярное выражение для сопоставления действительных адресов электронной почты довольно сложное.

Нам понадобится это регулярное выражение внутри объекта Pattern , чтобы мы могли его использовать:

Pattern EMAIL_ADDRESS_PATTERN = 
  Pattern.compile("([a-z0-9_.-]+)@([a-z0-9_.-]+[a-z])");

Мы рассмотрим два основных подхода, один из которых зависит от использования Java 9 или более поздней версии.

Для нашего примера текста мы попытаемся найти три письма в строке:

"You can contact me through [email protected], [email protected], and [email protected]"

3. Подсчет совпадений для Java 8 и старше

Во-первых, давайте посмотрим, как подсчитать совпадения с помощью Java 8 или старше.

Простой способ подсчета совпадений-это перебор метода find класса Matcher . Этот метод пытается найти следующую подпоследовательность входной последовательности, которая соответствует шаблону :

Matcher countEmailMatcher = EMAIL_ADDRESS_PATTERN.matcher(TEXT_CONTAINING_EMAIL_ADDRESSES);

int count = 0;
while (countEmailMatcher.find()) {
    count++;
}

Используя этот подход, мы найдем три совпадения, как и ожидалось:

assertEquals(3, count);

Обратите внимание, что метод find не сбрасывает Matcher после каждого найденного совпадения — он возобновляется, начиная с символа после окончания предыдущей совпадающей последовательности, поэтому поиск перекрывающихся адресов электронной почты не будет работать.

Например, давайте рассмотрим этот пример:

String OVERLAPPING_EMAIL_ADDRESSES = "Try to contact us at [email protected]@baeldung.com, [email protected]";

Matcher countOverlappingEmailsMatcher = EMAIL_ADDRESS_PATTERN.matcher(OVERLAPPING_EMAIL_ADDRESSES);

int count = 0;
while (countOverlappingEmailsMatcher.find()) {
    count++;
}

assertEquals(2, count);

Когда регулярное выражение пытается найти совпадения в данной строке , сначала оно найдет ” [email protected] ” в качестве совпадения. Поскольку перед @ нет доменной части, маркер не будет сброшен, а второй “@baeldung.com” будет проигнорирован. Двигаясь дальше, он также будет рассматривать ” [email protected] ” в качестве второго совпадения:

Как показано выше, у нас есть только два совпадения в перекрывающемся примере электронной почты.

4. Подсчет совпадений для Java 9 и более поздних версий

Однако, если у нас есть более новая версия Java, мы можем использовать метод results класса Matcher . Этот метод, добавленный в Java 9, возвращает последовательный поток результатов совпадений, что позволяет нам легче подсчитывать совпадения:

long count = countEmailMatcher.results()
  .count();

assertEquals(3, count);

Как мы видели с find , Соответствует не сбрасывается при обработке потока из метода results . Аналогично, метод results также не будет работать для поиска совпадений, которые перекрываются.

5. Заключение

В этой короткой статье мы узнали, как подсчитать совпадения регулярного выражения.

Во-первых, мы узнали, как использовать метод find с циклом while . Затем мы увидели, как новый метод потоковой передачи Java 9 позволяет нам делать это с меньшим количеством кода.

Как всегда, примеры кода доступны на GitHub .