Java как составить регулярное выражение

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

  1. Основы регулярных выражений
  2. Регулярные выражения в Java
  3. Примеры использования регулярных выражений в Java

Основы регулярных выражений

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

Определение

Регулярные выражения представляют собой формальный язык поиска и редактирования подстрок в тексте. Допустим, нужно проверить на валидность e-mail адрес. Это проверка на наличие имени адреса, символа @, домена, точки после него и доменной зоны.

Вот самая простая регулярка для такой проверки:

^[A-Z0-9+_.-]+@[A-Z0-9.-]+$

В коде регулярные выражения обычно обозначается как regex, regexp или RE.

Синтаксис RegEx

Символы могут быть буквами, цифрами и метасимволами, которые задают шаблон:

Есть и другие конструкции, с помощью которых можно сокращать регулярки:

  • d — соответствует любой одной цифре и заменяет собой выражение [0-9];
  • D — исключает все цифры и заменяет [^0-9];
  • w — заменяет любую цифру, букву, а также знак нижнего подчёркивания;
  • W — любой символ кроме латиницы, цифр или нижнего подчёркивания;
  • s — поиск символов пробела;
  • S — поиск любого непробельного символа.

Квантификаторы

Это специальные ограничители, с помощью которых определяется частота появления элемента — символа, группы символов, etc:

  • ? — делает символ необязательным, означает 0 или 1. То же самое, что и {0,1}.
  • *0 или более, {0,}.
  • +1 или более, {1,}.
  • {n} — означает число в фигурных скобках.
  • {n,m} — не менее n и не более m раз.
  • *? — символ ? после квантификатора делает его ленивым, чтобы найти наименьшее количество совпадений.

Примеры использования квантификаторов в регулярных выражениях

Примеры использования квантификаторов в регулярных выражениях

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

Также квантификаторов есть три режима:

"А.+а" //жадный режим — поиск самого длинного совпадения
"А.++а" //сверхжадный режим — как жадный, но без реверсивного поиска при захвате строки
"А.+?а" //ленивый режим — поиск самого короткого совпадения

По умолчанию квантификатор всегда работает в жадном режиме. Подробнее о квантификаторах в Java вы можете почитать здесь.

Примеры их использования рассмотрим чуть дальше.

Поскольку мы говорим о регекспах в Java, то следует учитывать спецификации данного языка программирования.

Экранирование символов в регулярных выражениях Java

В коде Java нередко можно встретить обратную косую черту : этот символ означает, что следующий за ним символ является специальным, и что его нужно особым образом интерпретировать. Так, n означает перенос строки. Посмотрим на примере:

String s = "Это спецсимвол Java. nОн означает перенос строки.";
System.out.println(s);

Результат:

Это спецсимвол Java.
Он означает перенос строки.

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

String regex = "\s";

Ключевые классы

Java RegExp обеспечиваются пакетом java.util.regex. Здесь ключевыми являются три класса:

  1. Matcher — выполняет операцию сопоставления в результате интерпретации шаблона.
  2. Pattern — предоставляет скомпилированное представление регулярного выражения.
  3. PatternSyntaxException — предоставляет непроверенное исключение, что указывает на синтаксическую ошибку, допущенную в шаблоне RegEx.

Также есть интерфейс MatchResult, который представляет результат операции сопоставления.

Примеры использования регулярных выражений в Java

e-mail адрес

В качестве первого примера мы упомянули регулярку, которая проверяет e-mail адрес на валидность. И вот как эта проверка выглядит в Java-коде:

List emails = new ArrayList();
emails.add("name@gmail.com");
//Неправильный имейл:
emails.add("@gmail.com");

String regex = "^[A-Za-z0-9+_.-]+@(.+)$";
Pattern pattern = Pattern.compile(regex);

for(String email : emails){
  Matcher matcher = pattern.matcher(email);
  System.out.println(email +" : "+ matcher.matches());
}

Результат:

name@gmail.com : true
@gmail.com : false

Телефонный номер

Регулярное выражение для валидации номера телефона:

^((8|+7)[- ]?)?((?d{3})?[- ]?)?[d- ]{7,10}$

Эта регулярка ориентирована на российские мобильные номера, а также на городские с кодом из трёх цифр. Попробуйте написать код самостоятельно по принципу проверки e-mail адреса.

IP адрес

А вот класс для определения валидности IP адреса, записанного в десятичном виде:

private static boolean checkIP(String input) {
    return input.matches("((0|1\d{0,2}|2([0-4][0-9]|5[0-5]))\.){3}(0|1\d{0,2}|2([0-4][0-9]|5[0-5]))");
}

Правильное количество открытых и закрытых скобок в строке

На каждую открытую должна приходиться одна закрытая скобка:

private static boolean checkExpression(String input) {
    Pattern pattern = Pattern.compile("\([\d+/*-]*\)");
    Matcher matcher = pattern.matcher(input);
    do {
      input = matcher.replaceAll("");
      matcher = pattern.matcher(input);
    } while (matcher.find());
    return input.matches("[\d+/*-]*");
}

Извлечение даты

Теперь давайте извлечём дату из строки:

private static String[] getDate(String desc) {
  int count = 0;
  String[] allMatches = new String[2];
  Matcher m = Pattern.compile("(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.](19|20)\d\d").matcher(desc);
  while (m.find()) {
    allMatches[count] = m.group();
    count++;
  }
  return allMatches;
}

Проверка:

public static void main(String[] args) throws Exception{
  String[] dates = getDate("coming from the 25/11/2020 to the 30/11/2020");
  System.out.println(dates[0]);
  System.out.println(dates[1]);
}

Результат:

25/11/2020
30/11/2020

А вот использование различных режимов квантификаторов, принцип работы которых мы рассмотрели чуть ранее.

Жадный режим

Pattern pattern = Pattern.compile("a+"); 
Matcher matcher = pattern .matcher("aaa"); 
   
while (matcher.find()){
       System.out.println("Найдено от " + matcher.start() + 
                          " до " + (matcher.end()-1));
}

Результат:

Найдено от 0 дo 2

В заданном шаблоне первый символ – a. Matcher сопоставляет его с каждым символом текста, начиная с нулевой позиции и захватывая всю строку до конца, в чём и проявляется его «жадность». Вот и получается, что заданная стартовая позиция – это 0, а последняя – 2.

Сверхжадный режим

Pattern pattern = Pattern.compile("a++"); 
Matcher matcher = pattern .matcher("aaa"); 
   
while (matcher.find()){
       System.out.println("Найдено от " + matcher.start() + 
                          " до " + (matcher.end()-1));
}

Результат:

Найдено от 0 дo 2

Принцип, как и в жадном режиме, только поиск заданного символа в обратном направлении не происходит. В приведённой строке всё аналогично: заданная стартовая позиция – это 0, а последняя – 2.

Ленивый режим

Pattern pattern = Pattern.compile("a+?"); 
Matcher matcher = pattern .matcher("aaa"); 
   
while (matcher.find()){
       System.out.println("Найдено от " + matcher.start() + 
                          " до " + (matcher.end()-1));
}

Результат:

Найдено от 0 дo 0
Найдено от 1 дo 1
Найдено от 2 дo 2

Здесь всё просто: самое короткое совпадение находится на первой, второй и третьей позиции заданной строки.

Выводы

Общий принцип использования регулярных выражений сохраняется от языка к языку, однако если мы всё-таки говорим о RegEx в конкретном языке программирования, следует учитывать его спецификации. В Java это экранирование символов, использование специальной библиотеки java.util.regex и её классов.

А какие примеры использования регулярных выражений в Java хотели бы видеть вы? Напишите в комментариях.

Время на прочтение
6 мин

Количество просмотров 305K

Вступление

Что Вы знаете о обработке строк в Java? Как много этих знаний и насколько они углублены и актуальны? Давайте попробуем вместе со мной разобрать все вопросы, связанные с этой важной, фундаментальной и часто используемой частью языка. Наш маленький гайд будет разбит на две публикации:

  1. String, StringBuffer, StringBuilder (реализация строк)
  2. Pattern, Matcher (регулярные выражения)

Сегодня поговорим о регулярных выражениях в Java, рассмотрим их механизм и подход к обработке. Также рассмотрим функциональные возможности пакета java.util.regex.


Регулярные выражения

Регулярные выражения (regular expressions, далее РВ) — мощное и эффективное средство для обработки текста. Они впервые были использованы в текстовых редакторах операционной системы UNIX (ed и QED) и сделали прорыв в электронной обработке текстов конца XX века. В 1987 году более сложные РВ возникли в первой версии языка Perl и были основаны на пакете Henry Spencer (1986), написанном на языке С. А в 1997 году, Philip Hazel разработал Perl Compatible Regular Expressions (PCRE) — библиотеку, что точно наследует функциональность РВ в Perl. Сейчас PCRE используется многими современными инструментами, например Apache HTTP Server.

Большинство современных языков программирования поддерживают РВ, Java не является исключением.

Механизм

Существует две базовые технологии, на основе которых строятся механизмы РВ:

  • Недетерминированный конечный автомат (НКА) — «механизм, управляемый регулярным выражением»
  • Детерминированный конечный автомат (ДКА) — «механизм, управляемый текстом»

НКА — механизм, в котором управление внутри РВ передается от компонента к компоненту. НКА просматривает РВ по одному компоненту и проверяет, совпадает ли компонент с текстом. Если совпадает — проверятся следующий компонент. Процедура повторяется до тех пор, пока не будет найдено совпадение для всех компонентов РВ (пока не получим общее совпадение).

ДКА — механизм, который анализирует строку и следит за всеми «возможными совпадениями». Его работа зависит от каждого просканированного символа текста (то есть ДКА «управляется текстом»). Даний механизм сканирует символ текста, обновляет «потенциальное совпадение» и резервирует его. Если следующий символ аннулирует «потенциальное совпадение», то ДКА возвращается к резерву. Нет резерва — нет совпадений.

Логично, что ДКА должен работать быстрее чем НКА (ДКА проверяет каждый символ текста не более одного раза, НКА — сколько угодно раз пока не закончит разбор РВ). Но НКА предоставляет возможность определять ход дальнейших событий. Мы можем в значительной степени управлять процессом за счет правильного написания РВ.

Регулярные выражения в Java используют механизм НКА.

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

Подход к обработке

В языках программирования существует три подхода к обработке РВ:

  • интегрированный
  • процедурный
  • объектно-ориентированный

Интегрированный подход — встраивание РВ в низкоуровневый синтаксис языка. Этот подход скрывает всю механику, настройку и, как следствие, упрощает работу программиста.
Функциональность РВ при процедурном и объектно-ориентированном подходе обеспечивают функции и методы соответственно. Вместо специальных конструкций языка, функции и методы принимают в качестве параметров строки и интерпретируют их как РВ.

Для обработки регулярных выражений в Java используют объектно-ориентированный подход.

Реализация

Для работы с регулярными выражениями в Java представлен пакет java.util.regex. Пакет был добавлен в версии 1.4 и уже тогда содержал мощный и современный прикладной интерфейс для работы с регулярными выражениями. Обеспечивает хорошую гибкость из-за использования объектов, реализующих интерефейс CharSequence.
Все функциональные возможности представлены двумя классами, интерфейсом и исключением:

Pattern

Класс Pattern представляет собой скомпилированное представление РВ. Класс не имеет публичных конструкторов, поэтому для создания объекта данного класса необходимо вызвать статический метод compile и передать в качестве первого аргумента строку с РВ:

// XML тэг в формате <xxx></xxx>
Pattern pattern = Pattern.compile("^<([a-z]+)([^>]+)*(?:>(.*)<\/\1>|\s+\/>)$");

Также в качестве второго параметра в метод compile можно передать флаг в виде статической константы класса Pattern, например:

// email адрес в формате xxx@xxx.xxx (регистр букв игнорируется)
Pattern pattern = Pattern.compile("^([a-z0-9_\.-]+)@([a-z0-9_\.-]+)\.([a-z\.]{2,6})$", Pattern.CASE_INSENSITIVE);

Таблица всех доступных констант и эквивалентных им флагов:

Constant Equivalent Embedded Flag Expression
1 Pattern.CANON_EQ
2 Pattern.CASE_INSENSITIVE (?i)
3 Pattern.COMMENTS (?x)
4 Pattern.MULTILINE (?m)
5 Pattern.DOTALL (?s)
6 Pattern.LITERAL
7 Pattern.UNICODE_CASE (?u)
8 Pattern.UNIX_LINES (?d)

Иногда нам необходимо просто проверить есть ли в строке подстрока, что удовлетворяет заданному РВ. Для этого используют статический метод matches, например:

// это hex код цвета?
if (Pattern.matches("^#?([a-f0-9]{6}|[a-f0-9]{3})$", "#8b2323")) { // вернет true
    // делаем что-то
}

Также иногда возникает необходимость разбить строку на массив подстрок используя РВ. В этом нам поможет метод split:

Pattern pattern = Pattern.compile(":|;");
String[] animals = pattern.split("cat:dog;bird:cow");
Arrays.asList(animals).forEach(animal -> System.out.print(animal + " "));
// cat dog bird cow 

Matcher и MatchResult

Matcher — класс, который представляет строку, реализует механизм согласования (matching) с РВ и хранит результаты этого согласования (используя реализацию методов интерфейса MatchResult). Не имеет публичных конструкторов, поэтому для создания объекта этого класса нужно использовать метод matcher класса Pattern:

// будем искать URL
String regexp = "^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$";
String url = "http://habrahabr.ru/post/260767/";

Pattern pattern = Pattern.compile(regexp);
Matcher matcher = pattern.matcher(url);

Но результатов у нас еще нет. Чтобы их получить нужно воспользоваться методом find. Можно использовать matches — этот метод вернет true только тогда, когда вся строка соответствует заданному РВ, в отличии от find, который пытается найти подстроку, которая удовлетворяет РВ. Для более детальной информации о результатах согласования можно использовать реализацию методов интерфейса MatchResult, например:

// IP адрес
String regexp = "(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)";
// для сравнения работы find() и matches()
String goodIp = "192.168.0.3";
String badIp = "192.168.0.3g";

Pattern pattern = Pattern.compile(regexp);

Matcher matcher = pattern.matcher(goodIp);
// matches() - true, find() - true
matcher = pattern.matcher(badIp);
// matches() - false, find() - true

// а теперь получим дополнительную информацию
System.out.println(matcher.find() ?
        "I found '"+matcher.group()+"' starting at index "+matcher.start()+" and ending at index "+matcher.end()+"." :
        "I found nothing!");
// I found the text '192.168.0.3' starting at index 0 and ending at index 11.

Также можно начинать поиск с нужной позиции используя find(int start). Стоит отметить что существует еще один способ поиска — метод lookingAt. Он начинает проверку совпадений РВ с начала строки, но не требует полного соответствия, в отличии от matches.
Класс предоставляет методы для замены текста в указанной строке:

appendReplacement(StringBuffer sb, String replacement) Реализует механизм «добавление-и-замена» (append-and-replace). Формирует обьект StringBuffer (получен как параметр) добавляя replacement в нужные места. Устанавливает позицию, которая соответствует end() последнего результата поиска. После этой позиции ничего не добавляет.
appendTail(StringBuffer sb) Используется после одного или нескольких вызовов appendReplacement и служит для добавления оставшейся части строки в объект класса StringBuffer, полученного как параметр.
replaceFirst(String replacement) Заменяет первую последовательность, которая соответствует РВ, на replacement. Использует вызовы методов appendReplacement и appendTail.
replaceAll(String replacement) Заменяет каждую последовательность, которая соответствует РВ, на replacement. Также использует методы appendReplacement и appendTail.
quoteReplacement(String s) Возвращает строку, в которой коса черта (‘ ‘) и знак доллара (‘ $ ‘) будут лишены особого смысла.
Pattern pattern = Pattern.compile("a*b");
Matcher matcher = pattern.matcher("aabtextaabtextabtextb the end");
StringBuffer buffer = new StringBuffer();

while (matcher.find()) {
    matcher.appendReplacement(buffer, "-");
    // buffer = "-" -> "-text-" -> "-text-text-" -> "-text-text-text-"
}
matcher.appendTail(buffer);
// buffer = "-text-text-text- the end"

PatternSyntaxException

Неконтролируемое (unchecked) исключение, возникает при синтаксической ошибке в регулярном выражении. В таблице ниже приведены все методы и их описание.

getDescription() Возвращает описание ошибки.
getIndex() Возвращает индекс строки, где была найдена ошибка в РВ
getPattern() Возвращает ошибочное РВ.
getMessage() getDescription() + getIndex() + getPattern()

Спасибо за внимание. Все дополнения, уточнения и критика приветствуются.

Java предоставляет пакет java.util.regex для сопоставления с шаблоном с регулярными выражениями. Регулярные выражения Java очень похожи на язык программирования Perl и очень просты в освоении.

Регулярное выражение(regular expressions) – это специальная последовательность символов, которая помогает вам сопоставлять или находить другие строки или наборы строк, используя специальный синтаксис, содержащийся в шаблоне. Их можно использовать для поиска, редактирования или манипулирования текстом и данными.

Шаблон поиска может быть любым из простого символа, фиксированной строки или сложного выражения, содержащего специальные символы, описывающие шаблон. Шаблон, определенный выражением, может совпадать один или несколько раз или не совпадать для данной строки.

Шаблон применяется к тексту слева направо. Как только исходный символ был найден, его нельзя уже использовать повторно. Например, выражение aba будет соответствовать ababababa только два раза (aba_aba__)

Пакет java.util.regex в основном состоит из следующих трех классов:

  1. Класс Pattern – Объект Pattern представляет собой скомпилированное представление регулярного выражения. Класс Pattern не предоставляет общедоступных конструкторов. Чтобы создать шаблон, вы должны сначала вызвать один из его открытых статических методов compile(), который затем вернет объект Pattern. Эти методы принимают выражение в качестве первого аргумента.
  2. Класс Matcher – объект Matcher – это механизм, который интерпретирует шаблон и выполняет операции сопоставления с входной строкой. Как и класс Pattern, Matcher не определяет общедоступных конструкторов. Вы получаете объект Matcher, вызывая метод matcher() для объекта Pattern.
  3. PatternSyntaxException – Объект PatternSyntaxException является непроверенным исключением, которое указывает на синтаксическую ошибку в образце выражения.

Простым примером является строка. Например, Hello World соответствует строке «Hello World». , (точка) является еще одним примером. Точка соответствует любому отдельному символу; будет соответствовать, например, «а» или «1».

выражение соответствие
это текст соответствует “это текст”
thiss+iss+text Соответствует слову «this», за которым следуют один или несколько пробелов, за которыми следует слово «is», за которыми следуют один или несколько пробелов, за которыми следует слово «text».
^d+(.d+)? ^ определяет, что выражение должно начинаться с начала новой строки. d + соответствует одной или нескольким цифрам. ? делает утверждение в скобках необязательным. . соответствует “.”, скобки используются для группировки. Соответствует, например, “5”, “1,5” и “2.21”.

Capturing groups

Группы захвата(Capturing groups) – это способ рассматривать несколько символов как единое целое. Они создаются путем помещения символов, которые будут сгруппированы, в набор скобок.

Например, (dog) создает одну группу, содержащую буквы «d», «o» и «g».

Группы захвата нумеруются путем подсчета открывающих скобок слева направо. В выражении ((A) (B (C))), например, есть четыре такие группы –

  1. ((A)(B(C)))
  2. (A)
  3. (B(C))
  4. (C)

Чтобы узнать, сколько групп присутствует в выражении, вызовите метод groupCount для объекта соответствия. Метод groupCount возвращает int, показывающий количество групп захвата, присутствующих в шаблоне сопоставителя.

Существует также специальная группа, группа 0, которая всегда представляет все выражение. Эта группа не включена в общее количество, сообщенное groupCount.

В следующем примере показано, как найти строку цифр из заданной буквенно-цифровой строки:

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

public class RegexMatches {

   public static void main( String args[] ) {
      // Строка для сканирования, чтобы найти шаблон.
      String line = "This order was placed for QT3000! OK?";
      String pattern = "(.*)(\d+)(.*)";

      // Создаем объект Pattern
      Pattern r = Pattern.compile(pattern);

      // Теперь создаем объект соответствия.
      Matcher m = r.matcher(line);
      if (m.find( )) {
         System.out.println("Found value: " + m.group(0) );
         System.out.println("Found value: " + m.group(1) );
         System.out.println("Found value: " + m.group(2) );
      }else {
         System.out.println("NO MATCH");
      }
   }
}

Это даст следующий результат:
Found value: This order was placed for QT3000! OK?
Found value: This order was placed for QT300
Found value: 0

Вот таблица со списком всех синтаксисов регулярных выражений, доступных в Java:

Subexpression Соответствия
^ Соответствует началу строки.
$ Соответствует концу строки.
. любому отдельному символу, кроме новой строки. Использование опции m позволяет ему соответствовать и новой строке.
[…] любому отдельному символу в скобках.
[^…] любому отдельному символу не в скобках.
A Начало всей строки.
z Конец всей строки.
Z Конец всей строки, кроме допустимого конечного terminator.
re* Соответствует 0 или более вхождений предыдущего выражения.
re+ Соответствует 1 или более из предыдущего.
re? Соответствует 0 или 1 вхождению предыдущего выражения.
re{ n} Совпадает ровно с числом вхождений предыдущего выражения.
re{ n,} Соответствует n или более вхождений предыдущего выражения.
re{ n, m} Соответствует не менее n и не более m вхождений предыдущего выражения.
a| b Соответствует либо a, либо b.
(re) Группирует регулярные выражения и запоминает сопоставленный текст.
(?: re) Группирует без запоминания сопоставленного текста.
(?> re) Соответствует независимому паттерну без возврата.
w Слову из символов.
W несловесным символам.
s Соответствует пробелу. Эквивалентно [tnrf].
S без пробелов.
d Соответствует цифрам. Эквивалентно [0-9].
D Совпадает с “не цифрами”.
A началу строки.
Z концу строки. Если новая строка существует, она совпадает непосредственно перед новой строкой.
z концу строки.
G точке, где закончился последний.
n Обратная ссылка для захвата номера группы “n”.
b Соответствует границам слов вне скобок. Соответствует возврату (0x08) внутри скобок.
B границам без слов.
n, t, etc. Сопоставляет переводы строк, возврат каретки, вкладки и т. д.
Q Escape (цитата) все символы до E.
E Завершает цитирование, начинающееся с Q.

Обратная косая черта имеет предопределенное значение в Java. Вы должны использовать двойную обратную косую черту \, чтобы определить одну обратную косую черту. Если вы хотите определить w, то вы должны использовать \w.

Методы класса Matcher

Вот список полезных методов экземпляра – Index methods предоставляют полезные значения индекса, которые точно показывают, где совпадение было найдено во входной строке.

Метод и описание
1 public int start()

Возвращает начальный индекс предыдущего match.

2 public int start(int group)
Возвращает начальный индекс подпоследовательности, захваченной данной группой во время предыдущей операции сопоставления.
3 public int end()
Возвращает смещение после последнего совпадения символов.
4 public int end(int group)
Возвращает смещение после последнего символа подпоследовательности, захваченной данной группой во время предыдущей операции сопоставления.

Методы Study

Методы Study проверяют входную строку и возвращают логическое значение, указывающее, найден ли шаблон.

Метод и описание
1 public boolean lookingAt()
Пытается сопоставить входную последовательность, начиная с начала, с шаблоном.
2 public boolean find()
Пытается найти следующую подпоследовательность входной последовательности, которая соответствует шаблону.
3 public boolean find(int start)
Сбрасывает это сопоставление и затем пытается найти следующую подпоследовательность входной последовательности, которая соответствует шаблону, начиная с указанного индекса.
4 public boolean matches()
Попытки сопоставить весь регион с паттерном.

Методы замены

Методы замены являются полезными методами для замены текста во входной строке.

метод и описание
1 public Matcher appendReplacement(StringBuffer sb, String replacement)

Реализует нетерминальный шаг добавления и замены.

2 public StringBuffer appendTail(StringBuffer sb)

Реализует шаг добавления и замены терминала.

3 public String replaceAll(String replacement)

Заменяет каждую подпоследовательность входной последовательности, которая соответствует шаблону с данной строкой замены.

4 public String replaceFirst(String replacement)

Заменяет первую подпоследовательность входной последовательности, которая соответствует шаблону с данной строкой замены.

5 public static String quoteReplacement(String s)

Возвращает буквенную замещающую строку для указанной строки. Этот метод создает строку, которая будет работать в качестве литеральной замены в методе appendReplacement класса Matcher.

Методы начала и конца

Ниже приведен пример, который подсчитывает, сколько раз слово cat (кот) появляется во входной строке:

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

public class RegexMatches {

   private static final String REGEX = "\bcat\b";
   private static final String INPUT = "cat cat cat cattie cat";

   public static void main( String args[] ) {
      Pattern p = Pattern.compile(REGEX);
      Matcher m = p.matcher(INPUT);   // get a matcher object
      int count = 0;

      while(m.find()) {
         count++;
         System.out.println("Match number "+count);
         System.out.println("start(): "+m.start());
         System.out.println("end(): "+m.end());
      }
   }
}

Получим результат:
Match number 1
start(): 0
end(): 3
Match number 2
start(): 4
end(): 7
Match number 3
start(): 8
end(): 11
Match number 4
start(): 19
end(): 22

Этот пример использует границы слов, чтобы гарантировать, что буквы “c” “a” “t” не являются просто подстрокой в более длинном слове. Это также дает некоторую полезную информацию о том, где во входной строке произошло совпадение.

Метод start возвращает начальный индекс подпоследовательности, захваченной данной группой во время предыдущей операции сопоставления, а end возвращает индекс последнего сопоставленного символа плюс один.

Методы поиска(lookingAt)

Методы match и LookingAt пытаются сопоставить входную последовательность с шаблоном. Разница, однако, заключается в том, что для matches требуется сопоставление всей входной последовательности, а для lookingAt – нет.

Оба метода всегда начинаются с начала строки ввода. Вот пример:

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

public class RegexMatches {

   private static final String REGEX = "foo";
   private static final String INPUT = "fooooooooooooooooo";
   private static Pattern pattern;
   private static Matcher matcher;

   public static void main( String args[] ) {
      pattern = Pattern.compile(REGEX);
      matcher = pattern.matcher(INPUT);

      System.out.println("Current REGEX is: "+REGEX);
      System.out.println("Current INPUT is: "+INPUT);

      System.out.println("lookingAt(): "+matcher.lookingAt());
      System.out.println("matches(): "+matcher.matches());
   }
}

Получим следующий результат:
Current REGEX is: foo
Current INPUT is: fooooooooooooooooo
lookingAt(): true
matches(): false

Методы replaceFirst и replaceAll

Методы replaceFirst и replaceAll заменяют текст, соответствующий заданному регулярному выражению. replaceFirst заменяет первое вхождение, а replaceAll заменяет все вхождения.

Вот пример, объясняющий их работу:

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

public class RegexMatches {

   private static String REGEX = "dog";
   private static String INPUT = "The dog says meow. " + "All dogs say meow.";
   private static String REPLACE = "cat";

   public static void main(String[] args) {
      Pattern p = Pattern.compile(REGEX);
      
      // получаем объект соответствия
      Matcher m = p.matcher(INPUT); 
      INPUT = m.replaceAll(REPLACE);
      System.out.println(INPUT);
   }
}

И теперь вывод:
The cat says meow. All cats say meow.

Методы appendReplace и appendTail

Класс Matcher также предоставляет методы appendReplacement и appendTail для замены текста.

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

public class RegexMatches {

   private static String REGEX = "a*b";
   private static String INPUT = "aabfooaabfooabfoob";
   private static String REPLACE = "-";
   public static void main(String[] args) {

      Pattern p = Pattern.compile(REGEX);
      
      Matcher m = p.matcher(INPUT);
      StringBuffer sb = new StringBuffer();
      while(m.find()) {
         m.appendReplacement(sb, REPLACE);
      }
      m.appendTail(sb);
      System.out.println(sb.toString());
   }
}

Вывод:
-foo-foo-foo-

Методы класса PatternSyntaxException

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

метод и описание
1 public String getDescription()

Получает описание ошибки.

2 public int getIndex()

Получает индекс ошибки.

3 public String getPattern()

Извлекает ошибочный шаблон регулярного выражения.

4 public String getMessage()

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

Примеры

Напишите регулярное выражение, которое соответствует любому номеру телефона.

Телефонный номер в этом примере состоит либо из 7 номеров подряд, либо из 3 номеров, пробела или тире, а затем из 4 номеров.

package regex.phonenumber;

import org.junit.Test;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;


public class CheckPhone {

    @Test
    public void testSimpleTrue() {
        String pattern = "\d\d\d([,\s])?\d\d\d\d";
        String s= "1233323322";
        assertFalse(s.matches(pattern));
        s = "1233323";
        assertTrue(s.matches(pattern));
        s = "123 3323";
        assertTrue(s.matches(pattern));
    }
}

В следующем примере проверяется, содержит ли текст число из 3 цифр.

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

import org.junit.Test;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

public class CheckNumber {


    @Test
    public void testSimpleTrue() {
        String s= "1233";
        assertTrue(test(s));
        s= "0";
        assertFalse(test(s));
        s = "29 Kasdkf 2300 Kdsdf";
        assertTrue(test(s));
        s = "99900234";
        assertTrue(test(s));
    }




    public static boolean test (String s){
        Pattern pattern = Pattern.compile("\d{3}");
        Matcher matcher = pattern.matcher(s);
        if (matcher.find()){
            return true;
        }
        return false;
    }

}

В следующем примере показано как извлечь все действительные ссылки с веб-страницы. Не учитывает ссылки, начинающиеся с «javascript:» или «mailto:».

package regex.weblinks;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class LinkGetter {
    private Pattern htmltag;
    private Pattern link;

    public LinkGetter() {
        htmltag = Pattern.compile("<a\b[^>]*href="[^>]*>(.*?)");
        link = Pattern.compile("href="[^>]*">");
    }

    public List getLinks(String url) {
        List links = new ArrayList();
        try {
            BufferedReader bufferedReader = new BufferedReader(
                    new InputStreamReader(new URL(url).openStream()));
            String s;
            StringBuilder builder = new StringBuilder();
            while ((s = bufferedReader.readLine()) != null) {
                builder.append(s);
            }

            Matcher tagmatch = htmltag.matcher(builder.toString());
            while (tagmatch.find()) {
                Matcher matcher = link.matcher(tagmatch.group());
                matcher.find();
                String link = matcher.group().replaceFirst("href="", "")
                        .replaceFirst("">", "")
                        .replaceFirst(""[\s]?target="[a-zA-Z_0-9]*", "");
                if (valid(link)) {
                    links.add(makeAbsolute(url, link));
                }
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return links;
    }

    private boolean valid(String s) {
        if (s.matches("javascript:.*|mailto:.*")) {
            return false;
        }
        return true;
    }

    private String makeAbsolute(String url, String link) {
        if (link.matches("http://.*")) {
            return link;
        }
        if (link.matches("/.*") && url.matches(".*$[^/]")) {
            return url + "/" + link;
        }
        if (link.matches("[^/].*") && url.matches(".*[^/]")) {
            return url + "/" + link;
        }
        if (link.matches("/.*") && url.matches(".*[/]")) {
            return url + link;
        }
        if (link.matches("/.*") && url.matches(".*[^/]")) {
            return url + link;
        }
        throw new RuntimeException("Cannot make the link absolute. Url: " + url
                + " Link " + link);
    }
}

Поиск дублированных слов.
b(w+)s+1b
b является границей слова и 1 ссылается на совпадение первой группы, то есть первого слова. (?!-in)b(w+) 1b находит повторяющиеся слова, если они не начинаются с “-in”. Добавьте (?S) для поиска по нескольким строкам.

Поиск элементов, которые начинаются с новой строки.
(ns*)title

Также можете посмотреть официальную документацию тут.

Пакет java.util.regex предоставляется Java с целью сопоставления регулярных выражений с шаблоном. Регулярные выражения Java характеризуются существенным сходством с языком программирования Perl и очень просты в освоении.

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

Пакет java.util.regex исходно состоит из следующих трех классов:

  • Pattern Class – объект класса Pattern представляет скомпилированное представление регулярного выражения. В классе Pattern публичный конструктор не предусмотрен. Для создания шаблона, вам сперва необходимо вызвать один из представленных публичных статичных методов compile(), который далее произведет возврат объекта класса Pattern. Регулярное выражение в данных методах принимается как первый аргумент.
  • Matcher Class – объект класса Matcher представляет механизм, который интерпретирует шаблон, а также производит операции сопоставления с вводимой строкой. Аналогично классу Pattern, Matcher не содержит публичных конструкторов. Объект класса Matcher может быть получен путем вызова метода matcher() на объекте класса Pattern.
  • PatternSyntaxException – объект класса PatternSyntaxException представляет непроверяемое исключение, которое обозначает синтаксическую ошибку в шаблоне регулярного выражения.

Группы сбора

Группы сбора представляют способ обращения с несколькими символами как с одной единицей. Они создаются путем размещения символов, которые предстоит сгруппировать, в серии круглых скобок. К примеру, регулярное выражение (dog) составляет отдельную группу, содержащую буквы “d”, “o”, и “g”.

Группы сбора нумеруются посредством определения числа открывающих круглых скобок слева направо. Так, в выражении ((A)(B(C))) присутствуют четыре подобные группы:

  • ((A)(B(C)))
  • (A)
  • (B(C))
  • (C)

Для определения числа групп, представленных в выражении, вызвать метод groupCount на объекте класса matcher в Java. Метод groupCount извлекает число типа int, отображающее количество групп сбора, представленных в сопоставляемом шаблоне.

Также имеется специальная группа, группа 0, которая во всех случаях представляет выражение в полном виде. Данная группа не включается в сумму, представленную методом groupCount.

Пример

Ниже рассмотрен пример регулярного выражения в Java, иллюстрирующий способ выявления строки цифр в представленных буквенно-цифровых строках.

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

public class RegexMatches {

   public static void main( String args[] ) {
      // Строка для сканирования, чтобы найти шаблон
      String str = "Крещение Руси произошло в 988 году! Не так ли?";
      String pattern = "(.*)(\d+)(.*)";

      // Создание Pattern объекта
      Pattern r = Pattern.compile(pattern);

      // Создание matcher объекта
      Matcher m = r.matcher(str);
      if (m.find( )) {
         System.out.println("Найдено значение: " + m.group(0));
         System.out.println("Найдено значение: " + m.group(1));
         System.out.println("Найдено значение: " + m.group(2));
      }else {
         System.out.println("НЕ СОВПАДАЕТ");
      }
   }
}

В итоге будет получен следующий результат:

Найдено значение: Крещение Руси произошло в 988 году! Не так ли?
Найдено значение: Крещение Руси произошло в 98
Найдено значение: 8

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

В Java регулярные выражения используют специальные символы. В следующей таблице представлены метасимволы доступные в синтаксисе регулярных выражений.

Подвыражение Обозначение символов
^ Соответствует началу строки.
$ Соответствует концу строки.
. Соответствует любому одиночному символу, за исключением новой строки. Использование опции m делает возможным соответствие новой строке.
[…] Соответствует любому одиночному символу в квадратных скобках.
[^…] Соответствует любому одиночному символу вне квадратных скобок.
A Начало целой строки.
z Конец целой строки.
Z Конец целой строки, за исключением допустимого терминатора конца строки.
re* Соответствует 0 либо более вхождений предыдущего выражения.
re+ Соответствует 1 либо более вхождений предыдущего выражения.
re? Соответствует 0 либо 1 вхождению предыдущего выражения.
re{ n} Соответствует заданному n числу вхождений предыдущего выражения.
re{ n,} Соответствует n или большему числу вхождений предыдущего выражения.
re{ n, m} Соответствует n как минимум и m в большинстве вложений предыдущего выражения.
a| b Соответствует a или b.
(re) Группирует регулярные выражения и запоминает сравниваемый текст.
(?: re) Группирует регулярные выражения, не запоминая сравниваемый текст.
(?> re) Соответствует независимому шаблону без возврата.
w Соответствует словесным символам.
W Соответствует символам, не образующим слова.
s Соответствует пробелу. Эквивалент [tnrf].
S Соответствует непробельному символу.
d Соответствует цифре. Эквивалент [0-9].
D Соответствует нечисловому символу.
A Соответствует началу строки.
Z Соответствует окончанию строки. При наличии новой строки, располагается перед ней.
z Соответствует концу строки.
G Соответствует точке, где оканчивается предыдущее совпадение.
n Обратная ссылка на группу сбора под номером “n”.
b Соответствует границе слова вне квадратных скобок. Соответствует возврату на одну позицию (0x08) внутри квадратных скобок.
B Соответствуют границам символов, не образующих слова.
n, t, etc. Соответствует символам перевода строки, возврата каретки, табуляции, и т.д.
Q Управление (цитирование) всех символов до символа E.
E Окончание цитаты, открытой при помощи Q.

Далее представлен список полезных методов экземпляра класса.

Методы индексов

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

№. Метод и описание
1 public int start()
Возврат начального индекса к предыдущему совпадению.
2 public int start(int group)
Возврат начального индекса к последовательности, захваченной данной группой в течение предыдущей операции установления соответствия.
3 public int end()
Возврат позиции смещения следом за последним совпадающим символом.
4 public int end(int group)
Возврат позиции смещения следом за последним символом к последовательности, захваченной данной группой в течение предыдущей операции установления соответствия.

Методы исследования

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

№. Метод и описание
1 public boolean lookingAt()
Предпринимает попытку поиска соответствия вводимой последовательности в начале области с шаблоном.
2 public boolean find()
Предпринимает попытку поиска следующей подпоследовательности в вводимой последовательности, соответствующей шаблону.
3 public boolean find(int start)
Сброс данного поиска соответствия и попытка поиска новой подпоследовательности в вводимой последовательности, соответствующей шаблону с указанного индекса.
4 public boolean matches()
Предпринимает попытку поиска совпадений во всей области с шаблоном.

Методы замены

Методы замены представляют полезные методы для замены текста в вводимой строке.

№. Метод и описание
1 public Matcher appendReplacement(StringBuffer sb, String replacement)
Производит нетерминальное присоединение и замену.
2 public StringBuffer appendTail(StringBuffer sb)
Производит терминальное присоединение и замену.
3 public String replaceAll(String replacement)
Заменяет каждую подпоследовательность в вводимой последовательности, совпадающей с шаблоном, указанным в замещающей строке.
4 public String replaceFirst(String replacement)
Замещает первую подпоследовательность в вводимой последовательности, совпадающей с шаблоном, указанным в замещающей строке.
5 public static String quoteReplacement(String s)
Возвращает литеральную замену Строки для указанной Строки. Данный метод производит сроку, которая будет функционировать в качестве литеральной замены s в методе appendReplacement класса Matcher.

Методы start и end

Далее представлен пример, в котором производится подсчет количества раз, когда в строке ввода встречается слово “кот”.

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

public class RegexMatches {

   private static final String REGEX = "\bкот\b";
   private static final String INPUT = "кот кот кот котёл кот";

   public static void main( String args[] ) {
      Pattern p = Pattern.compile(REGEX);
      Matcher m = p.matcher(INPUT);   // получение matcher объекта
      int count = 0;

      while(m.find()) {
         count++;
         System.out.println("Номер вхождения: "+count);
         System.out.println("Начальная позиция вхождения: "+m.start());
         System.out.println("Конечная позиция вхождения: "+m.end());
      }
   }
}

В итоге будет получен следующий результат:

Номер вхождения: 1
Начальная позиция вхождения: 0
Конечная позиция вхождения: 3
Номер вхождения: 2
Начальная позиция вхождения: 4
Конечная позиция вхождения: 7
Номер вхождения: 3
Начальная позиция вхождения: 8
Конечная позиция вхождения: 11
Номер вхождения: 4
Начальная позиция вхождения: 18
Конечная позиция вхождения: 21

Как видим, в данном примере используются границы слов с целью удостоверения в том, что буквы “c” “a” “t” не являются частью другого слова. Также отображаются определенные полезные сведения касательно нахождения совпадения в вводимой строке.

Метод start производит возврат начального индекса в последовательности, захваченной в данной группе в ходе предыдущей операции поиска совпадений, а end производит возврат индекса к последнему совпавшему символу, плюс один.

Методы matches и lookingAt

Оба метода matches и lookingAt направлены на попытку поиска соответствия вводимой последовательности с шаблоном. Разница, однако, заключается в том, что для метода matches требуется вся вводимая последовательность, в то время как lookingAt этого не требует.

Оба метода всегда начинаются в начале вводимой строки. Далее представлен пример, рассматривающий их функциональность.

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

public class RegexMatches {

   private static final String REGEX = "Pro";
   private static final String INPUT = "ProgLang";
   private static Pattern pattern;
   private static Matcher matcher;

   public static void main( String args[] ) {
      pattern = Pattern.compile(REGEX);
      matcher = pattern.matcher(INPUT);

      System.out.println("Текущее регулярное выражение: " + REGEX);
      System.out.println("Текущие входные данные: " + INPUT);

      System.out.println("lookingAt(): " + matcher.lookingAt());
      System.out.println("matches(): " + matcher.matches());
   }
}

В итоге будет получен следующий результат:

Текущее регулярное выражение: Pro
Текущие входные данные: ProgLang
lookingAt(): true
matches(): false

Методы replaceFirst и replaceAll

Методы replaceFirst и replaceAll производят замену текста, который совпадает с заданным регулярным выражением. Исходя из их названия, replaceFirst производит замену первого совпадения, а replaceAll производит замену остальных совпадений.

Далее представлен пример, поясняющий их функциональность.

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

public class RegexMatches {

   private static String REGEX = "Собака";
   private static String INPUT = "Собака говорит мяу.";
   private static String REPLACE = "Кот";

   public static void main(String[] args) {
      Pattern p = Pattern.compile(REGEX);
      
      // получение matcher объекта
      Matcher m = p.matcher(INPUT); 
      INPUT = m.replaceAll(REPLACE);
      System.out.println(INPUT);
   }
}

В итоге будет получен следующий результат:

Кот говорит мяу.

Методы appendReplacement и appendTail

Класс Matcher также предоставляет методы замены текста appendReplacement и appendTail.

Далее представлен пример, поясняющий их функциональность.

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

public class RegexMatches {

   private static String REGEX = "а*д";
   private static String INPUT = "аадProgLangааадProgLangадProgLangд";
   private static String REPLACE = "-";
   public static void main(String[] args) {

      Pattern p = Pattern.compile(REGEX);
      
      // получение matcher объекта
      Matcher m = p.matcher(INPUT);
      StringBuffer sb = new StringBuffer();
      while(m.find()) {
         m.appendReplacement(sb, REPLACE);
      }
      m.appendTail(sb);
      System.out.println(sb.toString());
   }
}

В итоге будет получен следующий результат:

-ProgLang-ProgLang-ProgLang-

Методы класса PatternSyntaxException

PatternSyntaxException представляет непроверяемое исключение, которое отображает синтаксическую ошибку в шаблоне регулярного выражения. Класс PatternSyntaxException представлен следующими методами, которые помогут определить вам ошибку.

№. Метод и описание
1 public String getDescription()
Представляет описание ошибки.
2 public int getIndex()
Представляет индекс ошибки.
3 public String getPattern()
Представляет шаблон регулярного выражения, содержащего ошибку.
4 public String getMessage()
Производит возврат многострочной строки, содержащей описание синтаксической ошибки и ее индекс, ошибочный образец регулярного выражения, а также визуальную индикацию индекса ошибки в шаблоне.

Java provides the java.util.regex package for pattern matching with regular expressions. Java regular expressions are very similar to the Perl programming language and very easy to learn.

A regular expression is a special sequence of characters that helps you match or find other strings or sets of strings, using a specialized syntax held in a pattern. They can be used to search, edit, or manipulate text and data.

The java.util.regex package primarily consists of the following three classes −

  • Pattern Class − A Pattern object is a compiled representation of a regular expression. The Pattern class provides no public constructors. To create a pattern, you must first invoke one of its public static compile() methods, which will then return a Pattern object. These methods accept a regular expression as the first argument.

  • Matcher Class − A Matcher object is the engine that interprets the pattern and performs match operations against an input string. Like the Pattern class, Matcher defines no public constructors. You obtain a Matcher object by invoking the matcher() method on a Pattern object.

  • PatternSyntaxException − A PatternSyntaxException object is an unchecked exception that indicates a syntax error in a regular expression pattern.

Capturing Groups

Capturing groups are a way to treat multiple characters as a single unit. They are created by placing the characters to be grouped inside a set of parentheses. For example, the regular expression (dog) creates a single group containing the letters “d”, “o”, and “g”.

Capturing groups are numbered by counting their opening parentheses from the left to the right. In the expression ((A)(B(C))), for example, there are four such groups −

  • ((A)(B(C)))
  • (A)
  • (B(C))
  • (C)

To find out how many groups are present in the expression, call the groupCount method on a matcher object. The groupCount method returns an int showing the number of capturing groups present in the matcher’s pattern.

There is also a special group, group 0, which always represents the entire expression. This group is not included in the total reported by groupCount.

Example

Following example illustrates how to find a digit string from the given alphanumeric string −

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

public class RegexMatches {

   public static void main( String args[] ) {
      // String to be scanned to find the pattern.
      String line = "This order was placed for QT3000! OK?";
      String pattern = "(.*)(\d+)(.*)";

      // Create a Pattern object
      Pattern r = Pattern.compile(pattern);

      // Now create matcher object.
      Matcher m = r.matcher(line);
      if (m.find( )) {
         System.out.println("Found value: " + m.group(0) );
         System.out.println("Found value: " + m.group(1) );
         System.out.println("Found value: " + m.group(2) );
      }else {
         System.out.println("NO MATCH");
      }
   }
}

This will produce the following result −

Output

Found value: This order was placed for QT3000! OK?
Found value: This order was placed for QT300
Found value: 0

Regular Expression Syntax

Here is the table listing down all the regular expression metacharacter syntax available in Java −

Subexpression Matches
^ Matches the beginning of the line.
$ Matches the end of the line.
. Matches any single character except newline. Using m option allows it to match the newline as well.
[…] Matches any single character in brackets.
[^…] Matches any single character not in brackets.
A Beginning of the entire string.
z End of the entire string.
Z End of the entire string except allowable final line terminator.
re* Matches 0 or more occurrences of the preceding expression.
re+ Matches 1 or more of the previous thing.
re? Matches 0 or 1 occurrence of the preceding expression.
re{ n} Matches exactly n number of occurrences of the preceding expression.
re{ n,} Matches n or more occurrences of the preceding expression.
re{ n, m} Matches at least n and at most m occurrences of the preceding expression.
a| b Matches either a or b.
(re) Groups regular expressions and remembers the matched text.
(?: re) Groups regular expressions without remembering the matched text.
(?> re) Matches the independent pattern without backtracking.
w Matches the word characters.
W Matches the nonword characters.
s Matches the whitespace. Equivalent to [tnrf].
S Matches the nonwhitespace.
d Matches the digits. Equivalent to [0-9].
D Matches the nondigits.
A Matches the beginning of the string.
Z Matches the end of the string. If a newline exists, it matches just before newline.
z Matches the end of the string.
G Matches the point where the last match finished.
n Back-reference to capture group number “n”.
b Matches the word boundaries when outside the brackets. Matches the backspace (0x08) when inside the brackets.
B Matches the nonword boundaries.
n, t, etc. Matches newlines, carriage returns, tabs, etc.
Q Escape (quote) all characters up to E.
E Ends quoting begun with Q.

Methods of the Matcher Class

Here is a list of useful instance methods −

Index Methods

Index methods provide useful index values that show precisely where the match was found in the input string −

Sr.No. Method & Description
1

public int start()

Returns the start index of the previous match.

2

public int start(int group)

Returns the start index of the subsequence captured by the given group during the previous match operation.

3

public int end()

Returns the offset after the last character matched.

4

public int end(int group)

Returns the offset after the last character of the subsequence captured by the given group during the previous match operation.

Study Methods

Study methods review the input string and return a Boolean indicating whether or not the pattern is found −

Sr.No. Method & Description
1

public boolean lookingAt()

Attempts to match the input sequence, starting at the beginning of the region, against the pattern.

2

public boolean find()

Attempts to find the next subsequence of the input sequence that matches the pattern.

3

public boolean find(int start)

Resets this matcher and then attempts to find the next subsequence of the input sequence that matches the pattern, starting at the specified index.

4

public boolean matches()

Attempts to match the entire region against the pattern.

Replacement Methods

Replacement methods are useful methods for replacing text in an input string −

Sr.No. Method & Description
1

public Matcher appendReplacement(StringBuffer sb, String replacement)

Implements a non-terminal append-and-replace step.

2

public StringBuffer appendTail(StringBuffer sb)

Implements a terminal append-and-replace step.

3

public String replaceAll(String replacement)

Replaces every subsequence of the input sequence that matches the pattern with the given replacement string.

4

public String replaceFirst(String replacement)

Replaces the first subsequence of the input sequence that matches the pattern with the given replacement string.

5

public static String quoteReplacement(String s)

Returns a literal replacement String for the specified String. This method produces a String that will work as a literal replacement s in the appendReplacement method of the Matcher class.

The start and end Methods

Following is the example that counts the number of times the word “cat” appears in the input string −

Example

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

public class RegexMatches {

   private static final String REGEX = "\bcat\b";
   private static final String INPUT = "cat cat cat cattie cat";

   public static void main( String args[] ) {
      Pattern p = Pattern.compile(REGEX);
      Matcher m = p.matcher(INPUT);   // get a matcher object
      int count = 0;

      while(m.find()) {
         count++;
         System.out.println("Match number "+count);
         System.out.println("start(): "+m.start());
         System.out.println("end(): "+m.end());
      }
   }
}

This will produce the following result −

Output

Match number 1
start(): 0
end(): 3
Match number 2
start(): 4
end(): 7
Match number 3
start(): 8
end(): 11
Match number 4
start(): 19
end(): 22

You can see that this example uses word boundaries to ensure that the letters “c” “a” “t” are not merely a substring in a longer word. It also gives some useful information about where in the input string the match has occurred.

The start method returns the start index of the subsequence captured by the given group during the previous match operation, and the end returns the index of the last character matched, plus one.

The matches and lookingAt Methods

The matches and lookingAt methods both attempt to match an input sequence against a pattern. The difference, however, is that matches requires the entire input sequence to be matched, while lookingAt does not.

Both methods always start at the beginning of the input string. Here is the example explaining the functionality −

Example

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

public class RegexMatches {

   private static final String REGEX = "foo";
   private static final String INPUT = "fooooooooooooooooo";
   private static Pattern pattern;
   private static Matcher matcher;

   public static void main( String args[] ) {
      pattern = Pattern.compile(REGEX);
      matcher = pattern.matcher(INPUT);

      System.out.println("Current REGEX is: "+REGEX);
      System.out.println("Current INPUT is: "+INPUT);

      System.out.println("lookingAt(): "+matcher.lookingAt());
      System.out.println("matches(): "+matcher.matches());
   }
}

This will produce the following result −

Output

Current REGEX is: foo
Current INPUT is: fooooooooooooooooo
lookingAt(): true
matches(): false

The replaceFirst and replaceAll Methods

The replaceFirst and replaceAll methods replace the text that matches a given regular expression. As their names indicate, replaceFirst replaces the first occurrence, and replaceAll replaces all occurrences.

Here is the example explaining the functionality −

Example

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

public class RegexMatches {

   private static String REGEX = "dog";
   private static String INPUT = "The dog says meow. " + "All dogs say meow.";
   private static String REPLACE = "cat";

   public static void main(String[] args) {
      Pattern p = Pattern.compile(REGEX);
      
      // get a matcher object
      Matcher m = p.matcher(INPUT); 
      INPUT = m.replaceAll(REPLACE);
      System.out.println(INPUT);
   }
}

This will produce the following result −

Output

The cat says meow. All cats say meow.

The appendReplacement and appendTail Methods

The Matcher class also provides appendReplacement and appendTail methods for text replacement.

Here is the example explaining the functionality −

Example

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

public class RegexMatches {

   private static String REGEX = "a*b";
   private static String INPUT = "aabfooaabfooabfoob";
   private static String REPLACE = "-";
   public static void main(String[] args) {

      Pattern p = Pattern.compile(REGEX);
      
      // get a matcher object
      Matcher m = p.matcher(INPUT);
      StringBuffer sb = new StringBuffer();
      while(m.find()) {
         m.appendReplacement(sb, REPLACE);
      }
      m.appendTail(sb);
      System.out.println(sb.toString());
   }
}

This will produce the following result −

Output

-foo-foo-foo-

PatternSyntaxException Class Methods

A PatternSyntaxException is an unchecked exception that indicates a syntax error in a regular expression pattern. The PatternSyntaxException class provides the following methods to help you determine what went wrong −

Sr.No. Method & Description
1

public String getDescription()

Retrieves the description of the error.

2

public int getIndex()

Retrieves the error index.

3

public String getPattern()

Retrieves the erroneous regular expression pattern.

4

public String getMessage()

Returns a multi-line string containing the description of the syntax error and its index, the erroneous regular expression pattern, and a visual indication of the error index within the pattern.

Добавить комментарий