1. Обзор
При работе с регулярными выражениями в Java мы обычно ищем последовательность символов для заданного шаблона . Чтобы облегчить это, API регулярных выражений Java предоставляет класс Matcher , который мы можем использовать для сопоставления данного регулярного выражения с текстом.
Как правило, мы почти всегда хотим использовать один из двух популярных методов класса Matcher :
- находить()
- спички()
В этом кратком руководстве мы узнаем о различиях между этими методами, используя простой набор примеров.
2. Метод find()
Проще говоря, метод find() пытается найти вхождение шаблона регулярного выражения в заданной строке . Если в строке найдено несколько вхождений, то первый вызов функции find() перейдет к первому вхождению. После этого каждый последующий вызов метода find() будет один за другим переходить к следующему совпадающему вхождению.
Давайте представим, что мы хотим найти предоставленную строку “до свидания 2019 и добро пожаловать 2020” только для четырехзначных чисел.
Для этого мы будем использовать шаблон “\\d\\d\\d\\d” :
@Test public void whenFindFourDigitWorks_thenCorrect() { Pattern stringPattern = Pattern.compile("\\d\\d\\d\\d"); Matcher m = stringPattern.matcher("goodbye 2019 and welcome 2020"); assertTrue(m.find()); assertEquals(8, m.start()); assertEquals("2019", m.group()); assertEquals(12, m.end()); assertTrue(m.find()); assertEquals(25, m.start()); assertEquals("2020", m.group()); assertEquals(29, m.end()); assertFalse(m.find()); }
Как у нас есть два случая в этом примере– 2019 и 2020 – метод find() дважды вернет true , и как только он достигнет конца области соответствия, он вернет false .
Как только мы найдем какое-либо совпадение, мы можем использовать такие методы, как start () , group () и end () , чтобы получить более подробную информацию о совпадении , как показано выше.
Метод start() даст начальный индекс совпадения, end() вернет последний индекс символа после окончания совпадения, а group() вернет фактическое значение совпадения .
3. Метод find(int)
У нас также есть перегруженная версия метода find — find(int) . Он принимает начальный индекс в качестве параметра и рассматривает startindex в качестве отправной точки для поиска вхождений в строке .
Давайте посмотрим, как использовать этот метод в том же примере, что и раньше:
@Test public void givenStartIndex_whenFindFourDigitWorks_thenCorrect() { Pattern stringPattern = Pattern.compile("\\d\\d\\d\\d"); Matcher m = stringPattern.matcher("goodbye 2019 and welcome 2020"); assertTrue(m.find(20)); assertEquals(25, m.start()); assertEquals("2020", m.group()); assertEquals(29, m.end()); }
Поскольку мы предоставили начальный индекс 20 , мы видим, что в настоящее время найдено только одно вхождение — 2020, которое происходит, как и ожидалось, после этого индекса . И, как в случае с find() , мы можем использовать такие методы, как start() , group () и end () , чтобы извлечь более подробную информацию о совпадении.
4. Метод matches()
С другой стороны, метод |/matches() пытается сопоставить всю строку с шаблоном .
В том же примере matches() вернет false :
@Test public void whenMatchFourDigitWorks_thenFail() { Pattern stringPattern = Pattern.compile("\\d\\d\\d\\d"); Matcher m = stringPattern.matcher("goodbye 2019 and welcome 2020"); assertFalse(m.matches()); }
Это связано с тем, что он попытается сопоставить “\\d\\d\\d\\d” со всей строкой ” до свидания 2019 и добро пожаловать 2020″ — в отличие от методов find() и find(int) , оба из которых найдут вхождение шаблона в любом месте строки .
Если мы изменим строку на четырехзначное число “2019” , то matches() вернет true :
@Test public void whenMatchFourDigitWorks_thenCorrect() { Pattern stringPattern = Pattern.compile("\\d\\d\\d\\d"); Matcher m = stringPattern.matcher("2019"); assertTrue(m.matches()); assertEquals(0, m.start()); assertEquals("2019", m.group()); assertEquals(4, m.end()); assertTrue(m.matches()); }
Как показано выше, мы также можем использовать такие методы, как start () , group () и end () , чтобы собрать более подробную информацию о матче. Один интересный момент, который следует отметить, заключается в том, что вызов find() несколько раз может возвращать разные выходные данные после вызова этих методов, как мы видели в нашем первом примере, но matches() всегда будет возвращать одно и то же значение.
5. Заключение
В этой статье мы видели, как find() , find(int) и matches() отличаются друг от друга на практическом примере. Мы также видели, как различные методы , такие как start () , group () и end () , могут помочь нам извлечь более подробную информацию о данном совпадении .
Как всегда, полный исходный код статьи доступен на GitHub .