Android что такое matches

Android что такое matches

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

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

split

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

Например, разделим предложение на слова:

Для разделения применяется регулярное выражение «\\s*(\\s|,|!|\\.)\\s*». Подвыражние «\\s» по сути представляет пробел. Звездочка указывает, что символ может присутствовать от 0 до бесконечного количества раз. То есть добавляем звездочку и мы получаем неопределенное количество идущих подряд пробелов — «\\s*» (то есть неважно, сколько пробелов между словами). Причем пробелы может вообще не быть. В скобках указывает группа выражений, которая может идти после неопределенного количества пробелов. Группа позволяет нам определить набо значений через вертикальную черту, и подстрока должна соответствовать одному из этих значений. То есть в группе «\\s|,|!|\\.» подстрока может соответствовать пробелу, запятой, восклицательному знаку или точке. Причем поскольку точка представляет специальную последовательность, то, чтобы указать, что мы имеем в виду имеено знак точки, а не специальную последовательность, перед точкой ставим слеши.

Соответствие строки. matches

Еще один метод класса String — matches() принимает регулярное выражение и возвращает true, если строка соответствует этому выражению. Иначе возвращает false.

Например, проверим, соответствует ли строка номеру телефона:

В данном случае в регулярном выражение сначала определяется группа «(\\+*)». То есть вначале может идти знак плюса, но также он может отсутствовать. Далее смотрим, соответствуют ли последующие 11 символов цифрам. Выражение «\\d» представляет цифровой символ, а число в фигурных скобках — <11>— сколько раз данный тип символов должен повторяться. То есть мы ищем строку, где вначале может идти знак плюс (или он может отсутствовать), а потом идет 11 цифровых символов.

Класс Pattern

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

Само регулярное выражение представляет шаблон для поиска совпадений в строке. Для задания подобного шаблона и поиска подстрок в строке, которые удовлетворяют данному шаблону, в Java определены классы Pattern и Matcher .

Для простого поиска соответствий в классе Pattern определен статический метод boolean matches(String pattern, CharSequence input) . Данный метод возвращает true, если последовательность символов input полностью соответствует шаблону строки pattern:

Но, как правило, для поиска соответствий применяется другой способ — использование класса Matcher.

Класс Matcher

Рассмотрим основные методы класса Matcher:

boolean matches() : возвращает true, если вся строка совпадает с шаблоном

boolean find() : возвращает true, если в строке есть подстрока, которая совпадает с шаблоном, и переходит к этой подстроке

String group() : возвращает подстроку, которая совпала с шаблоном в результате вызова метода find. Если совпадение отсутствует, то метод генерирует исключение IllegalStateException .

int start() : возвращает индекс текущего совпадения

int end() : возвращает индекс следующего совпадения после текущего

String replaceAll(String str) : заменяет все найденные совпадения подстрокой str и возвращает измененную строку с учетом замен

Используем класс Matcher. Для этого вначале надо создать объект Pattern с помощью статического метода compile() , который позволяет установить шаблон:

В качестве шаблона выступает строка «Hello». Метод compile() возвращает объект Pattern, который мы затем можем использовать в программе.

В классе Pattern также определен метод matcher(String input) , который в качестве параметра принимает строку, где надо проводить поиск, и возвращает объект Matcher :

Затем у объекта Matcher вызывается метод matches() для поиска соответствий шаблону в тексте:

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

Допустим, мы хотим найти в строке все вхождения слова Java. В исходной строке это три слова: «Java», «JavaScript» и «JavaSE». Для этого применим шаблон «Java(\\w*)». Данный шаблон использует синтаксис регулярных выражений. Слово «Java» в начале говорит о том, что все совпадения в строке должны начинаться на Java. Выражение (\\w*) означает, что после «Java» в совпадении может находиться любое количество алфавитно-цифровых символов. Выражение \w означает алфавитно-цифровой символ, а звездочка после выражения указывает на неопределенное их количество — их может быть один, два, три или вообще не быть. И чтобы java не рассматривала \w как эскейп-последовательность, как \n, то выражение экранируется еще одним слешем.

Читайте также:  Как перепрошить мертвый андроид через компьютер

Далее применяется метод find() класса Matcher, который позволяет переходить к следующему совпадению в строке. То есть первый вызов этого метода найдет первое совпадение в строке, второй вызов найдет второе совпадение и т.д. То есть с помощью цикла while(matcher.find()) мы можем пройтись по всем совпадениям. Каждое совпадение мы можем получить с помощью метода matcher.group() . В итоге программа выдаст следующий результат:

Замена в строке

Теперь сделаем замену всех совпадений с помощью метода replaceAll() :

Также надо отметить, что в классе String также имеется метод replaceAll() с подобным действием:

Разделение строки на лексемы

С помощью метода String[] split(CharSequence input) класса Pattern можно разделить строку на массив подстрок по определенному разделителю. Например, мы хотим выделить из строки отдельные слова:

И консоль выведет набор слов:

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

Теперь у нас останутся только слова:

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

Источник

Обработка строк в Java. Часть II: Pattern, Matcher

Вступление

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

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

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

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

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

Механизм

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

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

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

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

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

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

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

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

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

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

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

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

Реализация

Pattern

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

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

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

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

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, например:

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

Matcher и MatchResult

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

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

Источник

Использование класса Java Matcher в регулярных выражениях

Класс Java Matcher (java.util.regex.Matcher) используется для поиска в тексте нескольких вхождений регулярного выражения. Вы также можете использовать его для поиска одного и того же выражения в разных текстах.

Пример

Сначала экземпляр Pattern создается из регулярного выражения, а из экземпляра Pattern создается экземпляр Matcher. Затем метод matches() вызывается для экземпляра Matcher. Он возвращает true, если регулярное выражение соответствует тексту, и false, если нет.

Создание

Создание выполняется с помощью метода matcher() в классе Pattern:

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

matches()

Метод matches() в классе Matcher сопоставляет регулярное выражение со всем текстом, переданным методу Pattern.matcher() при создании Matcher:

Если выражение соответствует всему тексту, то метод matches() возвращает true. Если нет, возвращает false.

Вы не можете использовать метод matches() для поиска нескольких вхождений выражения в тексте. Для этого вам нужно использовать методы find(), start() и end().

lookingAt()

Метод работает подобно методу matches() с одним существенным отличием. Он сопоставляет регулярное выражение только с началом текста, тогда как matches() сопоставляет с целым текстом. Другими словами, если выражение соответствует началу текста, но не всему тексту, lookAt() вернет true, тогда как matches() вернет false:

Этот пример сопоставляет регулярное выражение «This is the» как с началом текста, так и со всем текстом. Сопоставление с началом текста (lookingAt()) вернет true.

Сопоставление со всем текстом (matches()) вернет false, потому что текст содержит больше символов, чем выражение, а оно говорит, что текст должен точно соответствовать тексту «This», без лишних символов до или после.

find() + start() + end()

Метод find() ищет вхождения выражений в тексте, переданном методу Pattern.matcher(text) при создании Matcher. Если в тексте можно найти несколько совпадений, метод найдет первое, а затем при каждом последующем вызове будет переходить к следующему совпадению.

Методы start() и end() передадут индексы в текст, где найденное совпадение начинается и заканчивается. На самом деле end() возвращает индекс символа конца соответствующего раздела. Таким образом, вы можете использовать возвращаемые значения start() и end() внутри вызова String.substring().

Этот пример найдет шаблон «is» четыре раза в искомой строке. Вывод будет напечатан так:

reset()

Метод reset() сбрасывает внутреннее состояние соответствия в Matcher. В случае, если вы начали сопоставлять вхождения в строке с помощью метода find(), будет внутренне сохраняться состояние о том, как далеко он провел поиск во входном тексте. При вызове reset() сопоставление снова начнется с начала текста.

Существует также метод сброса (CharSequence). Он сбрасывает Matcher и выполняет поиск через CharSequence, переданный в качестве параметра, вместо CharSequence, с которой изначально был создан Matcher.

Читайте также:  Which init android users

group()

Представьте, что вы ищете в тексте URL-адреса, и вы хотели бы извлечь найденные URL-адреса из текста. Конечно, вы можете сделать это с помощью методов start() и end(), но это проще сделать с помощью групповых функций.

Группы отмечены круглыми скобками:

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

Доступ к группе осуществляется с помощью метода group(int groupNo). Выражение может иметь более одной группы. Таким образом, каждая группа помечается отдельным набором скобок. Чтобы получить доступ к тексту, который соответствует части выражения в определенной группе, передайте номер группы методу group(int groupNo).

Группа с номером 0 всегда является целым выражением. Чтобы получить доступ к группе, отмеченной круглыми скобками, вы должны начать с номера группы 1.

Этот пример ищет в тексте вхождения слова John. Для каждого найденного совпадения извлекается группа № 1, которая соответствует группе, отмеченной круглыми скобками. Результат примера:

Несколько групп

Как упоминалось ранее, регулярное выражение может иметь несколько групп:

Это выражение соответствует тексту «John», за которым следует пробел, а затем один или несколько символов. Вы не можете видеть это в примере выше, но после последней группы есть пробел.

Это выражение содержит несколько символов со специальным значением.

  • . означает «любой символ».
  • Знак + означает «один или несколько раз» и относится к. (Любой символ, один или несколько раз).
  • ? означает «сопоставить как можно меньшее количество символов».

Вот полный пример кода:

Обратите внимание на ссылку на две группы. Символы, соответствующие этим группам, печатаются в System.out. Вот что распечатывает пример:

Группы внутри групп

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

Когда группы вложены друг в друга, они нумеруются в зависимости от того, когда встречается левый парантез группы. Таким образом, группа 1 является большой группой. Группа 2 – это группа с выражением John внутри. Группа 3 – это группа с выражением. +? внутри. Это важно знать, когда вам нужно ссылаться на группы с помощью метода groups(int groupNo).

Вот пример, который использует вышеупомянутые вложенные группы:

Обратите внимание, что значение, сопоставленное первой группой (внешней группой), содержит значения, сопоставленные обеими внутренними группами.

replaceAll() + replaceFirst()

Методы replaceAll() и replaceFirst() можно использовать для замены частей строки, в которой ищет Matcher. Метод replaceAll() заменяет все совпадения. ReplaceFirst() заменяет только первое совпадение.

Перед выполнением любого сопоставления Matcher сбрасывается, поэтому сопоставление начинается с начала входного текста.

Вот два примера:

И вот что выводит пример:

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

Обратите внимание, что первая напечатанная строка содержит все вхождения John со словом после, замененным строкой Joe Blocks. Вторая строка заменяет только первое вхождение.

appendReplacement() + appendTail()

Методы appendReplacement() и appendTail() используются для замены строковых токенов во входном тексте и добавления результирующей строки в StringBuffer.

Когда нашли совпадение с помощью метода find(), вы можете вызвать appendReplacement(). Это приводит к тому, что символы из входного текста добавляются в StringBuffer, а соответствующий текст заменяется. Копируются только символы, начиная с конца последнего совпадения и до того момента, когда совпадающие символы будут скопированы.

Метод appendReplacement() отслеживает то, что было скопировано в StringBuffer, поэтому вы можете продолжать поиск совпадений с помощью find(), пока во входном тексте совпадений не будет найдено.

Как только будет найдено последнее совпадение, часть входного текста все равно не будет скопирована в StringBuffer. Это символы с конца последнего совпадения и до конца введенного текста. Вызывая appendTail(), вы также можете добавить эти последние символы в StringBuffer.

Обратите внимание, как appendReplacement() вызывается внутри цикла while(matcher.find()), а appendTail() вызывается сразу после цикла.

Выход из этого примера:

Разрыв строки в последней строке вставлен мной, чтобы сделать текст более читабельным. В реальном выводе не было бы разрыва строки.

Как видите, StringBuffer состоит из символов и замен из входного текста, по одному совпадению за раз.

Источник

Оцените статью