Особенности работы класса Matcher

Класс Matcher предназначен для работы с регулярными выражениями.

Матчер применяется на ко всей строке, а к предварительно установленному «региону». По умолчанию он совпадает со всей строкой. При необходимости его можно изменять. С помощью методов regionStart и regionEnd можно посмотреть установленные границы. Для изменения границ существует метод region.

У экземпляров объекта Matcher есть свойство transparentBounds, с помощью которого можно разрешить регулярному выражению выходить за границы региона, но только в том случае, если совпадающая подстрока находится в границах заданного региона. Если отключить свойство anchoringBounds, то границы региона не будут трактоваться как границы строки.

Чаще всего регулярные выражения применяют для поиска и замены. Для проверки, соответствует ли выражению весь установленный регион, используется метод matches. совпадение начало региона применяется метод lookingAt. Метод find последовательно  просматривает всю строку и ищет следующее совпадение. В нём, с помощью необязательного параметра, можно задать позицию в строке, с которой следует начать поиск.

С помощью интерфейса MatchResult, который реализован в Matcher, можно получить и обработать информацию о результатах поиска

Для получения данных о последнем успешном поиске в виде иммутабельного (неизменяемого) объекта применяется метод toMatchResult(). Чтобы получить все совпадения в виде потока (stream) следует использовать метод results().

Кроме этого в интерфейсе MatchReslut есть следующие методы:

  • group – возвращает найденную подстроку;
  • start – возвращает начальную позицию искомой подстроки в исходно строке;
  • end – возвращает конечную позицию найденной подстроки в строке.

В Matcher также есть такие интересные функции:

  • hitEnd – показывает, достигнут ли конец региона;
  • requireEnd – определяет, может ли измениться результат поиска при наличии в конце региона «хвоста»;
  • reset сбрасывает состояние поиска до начального, кроме этого в нем присутствует параметр, с помощью которого можно заменить строку для поиска;
  • usePattern – меняет регулярное выражение, но результаты поиска при этом не сбрасываются.

Чтобы произвести замену подстроки, эквивалентные регулярному выражению, существуют методы replaceFirst и replaceAll, в которые передаётся новая строка. В

результате выполнения обе функции сбрасывают состояние. Символ $ используется для ссылки на группы, а / для escape-последовательностей. Чтобы символы использовались без дополнительного смысла, требуется обернуть строку в вызов quoteReplacement.

Можно также искать совпадения вручную, после чего менять его в StringBuilder или StringBuffer используя метод appendReplacement. Хвост добавляется с помощью appendTail. В результате последовательность вызовов m.find, m.appendReplacement, и m.appendTail() выполняет то же что и m.replaceFirst, а последовательность while(m.find), m.appendReplacement и m.appendTail эквивалентно m.replaceAll.

StringBuilder sb = new StringBuilder();
Set<Integer> foundNumbers = new HashSet<>();
// Выражение: число с последующим пробелом, возможно с ; на конце (но тогда после должен быть "хвост")
Pattern р = Pattern.compile("(\\d+)\\s(; (?=хвост))?");
Matcher m = p.matcher(input: "Пример: 11 2 33 ;хвост");
m.region(0, 18); // Часть "хвост" не входит в регион, “;” еще входит
m.useTransparentBounds(true); 
// Это позволяет оператору lookahead видеть "хвост" за регионом
assert !m.matches(); 
// Хоть подходящие подстроки и есть, вся строка целиком не матчится.
boolean found = m.find();
while (found) {
  // Добавляет несматченный пройденный кусок строки ("Пример: " на первом 
  // шаге) как есть, в сматченном заменяет пробел после числа (первой 
  // группы) на символ доллара 
  m.appendReplacement(sb, replacement: "$1" +  Matcher.quoteReplacementi s: "$"));

  // Использование find+append позволяет совершить дополнительные 
  // действия, например, копить найденные числа в сет. 
  foundNumbers.add(Integer.parselnt(m.group(1)));
  found = m.find();
}
m.appendTail(sb);
// Прицепляем оставшийся несматченный хвост (этот метод игнорирует
// границы региона)
assert "Пример: 11$2$33$XBOCT".equals(sb.toString());
assert foundNumbers.containsAll(asList(11, 2, 33));
Поделиться уроком

Ответить

Ваш адрес email не будет опубликован. Обязательные поля помечены *