Методы для работы с захватываемыми группами
Исходный код приложенияRegexDemo
включает вызов метода m.group()
.
Метод group()
– один из нескольких методов класса Matcher
, ориентированных на работу с захватываемыми группами:
Метод
int groupCount()
возвращает число захватываемых групп в шаблоне сопоставителя. Это количество не учитывает специальную захватываемую группу номер 0, соответствующую шаблону в целом.Метод
String group()
возвращает символы предыдущего найденного совпадения. Чтобы сообщить об успешном поиске по пустой строке, этот метод возвращает пустую строку. Если сопоставитель еще не выполнял поиска или предыдущая операция поиска завершилась неудачей, генерируется исключениеIllegalStateException
.Метод
String group(int group)
напоминает предыдущий метод, за исключением того, что возвращает символы предыдущего найденного совпадения, захваченные группой, номер которой задается параметромgroup
. Обратите внимание, чтоgroup(0)
эквивалентноgroup()
. Если в шаблоне нет захватываемой группы с заданным номером, метод генерирует исключениеIndexOutOfBoundsException
. Если сопоставитель еще не выполнял поиска или предыдущая операция поиска завершилась неудачей, генерируется исключениеIllegalStateException
.Метод
String group(String name)
возвращает символы предыдущего найденного совпадения, захваченные группой name. Если захватываемой группы name в шаблоне нет, генерируется исключениеIllegalArgumentException
. Если сопоставитель еще не выполнял поиска или предыдущая операция поиска завершилась неудачей, генерируется исключениеIllegalStateException
.
groupCount()
и group(int group)
:
Pattern p = Pattern.compile("(.(.(.)))");
Matcher m = p.matcher("abc");
m.find();
System.out.println(m.groupCount());
for (int i = 0; i <= m.groupCount(); i++)
System.out.println(i + ": " + m.group(i));
Результаты выполнения:
3
0: abc
1: abc
2: bc
3: c
Методы для определения позиций совпадений
КлассMatcher
предоставляет несколько методов, возвращающих начальную и конечную позиции совпадения:
Метод
int start()
возвращает начальную позицию предыдущего найденного совпадения. Если сопоставитель еще не выполнял поиска или предыдущая операция поиска завершилась неудачей, генерируется исключениеIllegalStateException
.Метод
int start(int group)
напоминает предыдущий метод, но возвращает начальную позицию предыдущего найденного совпадения для группы, номер которой задается параметромgroup
. Если в шаблоне нет захватываемой группы с заданным номером, метод генерирует исключениеIndexOutOfBoundsException
. Если сопоставитель еще не выполнял поиска или предыдущая операция поиска завершилась неудачей, генерируется исключениеIllegalStateException
.Метод
int start(String name)
напоминает предыдущий метод, но возвращает начальную позицию предыдущего найденного совпадения для группы с названиемname
. Если захватываемой группыname
в шаблоне нет, генерируется исключениеIllegalArgumentException
. Если сопоставитель еще не выполнял поиска или предыдущая операция поиска завершилась неудачей, генерируется исключениеIllegalStateException
.Метод
int end()
возвращает позицию последнего из символов предыдущего найденного совпадения плюс 1. Если сопоставитель еще не выполнял поиска или предыдущая операция поиска завершилась неудачей, генерируется исключениеIllegalStateException
.Метод
int end(int group)
напоминает предыдущий метод, но возвращает конечную позицию предыдущего найденного совпадения для группы, номер которой задается параметромgroup
. Если в шаблоне нет захватываемой группы с заданным номером, метод генерирует исключениеIndexOutOfBoundsException
. Если сопоставитель еще не выполнял поиска или предыдущая операция поиска завершилась неудачей, генерируется исключениеIllegalStateException
.Метод
int end(String name)
напоминает предыдущий метод, но возвращает конечную позицию предыдущего найденного совпадения для группы с названиемname
. Если захватываемой группыname
в шаблоне нет, генерируется исключениеIllegalArgumentException
. Если сопоставитель еще не выполнял поиска или предыдущая операция поиска завершилась неудачей, генерируется исключениеIllegalStateException
.
Pattern p = Pattern.compile("(.(.(.)))");
Matcher m = p.matcher("abcabcabc");
while (m.find())
{
System.out.println("Найдено " + m.group(2));
System.out.println(" начинается с позиции " + m.start(2) +
" и заканчивается на позиции " + (m.end(2) - 1));
System.out.println();
}
В результате выполнения этого примера выводится следующее:
Найдено bc
начинается с позиции 1 и заканчивается на позиции 2
Найдено bc
начинается с позиции 4 и заканчивается на позиции 5
Найдено bc
начинается с позиции 7 и заканчивается на позиции 8
Методы класса PatternSyntaxException
Экземпляр классаPatternSyntaxException
описывает синтаксическую ошибку в регулярном выражении. Генерирует такое исключение из методов compile()
и matches()
класса Pattern
, а формируется посредством следующего конструктора:
PatternSyntaxException(String desc, String regex, int index)
Этот конструктор сохраняет указанное описание (desc
), регулярное выражение (regex
) и позицию, на которой произошла синтаксическая ошибка. Если место синтаксической ошибки неизвестно, значение index
устанавливается равным -1
.
Скорее всего, вам никогда не понадобится создавать экземпляры класса PatternSyntaxException
. Тем не менее, нужно будет извлекать вышеупомянутые значения при создании форматированного сообщения об ошибке. Для этого можно воспользоваться следующими методами:
- Метод
String getDescription()
возвращает описание синтаксической ошибки. - Метод
int getIndex()
возвращает или позицию, на которой произошла ошибка, или -1, если позиция неизвестна. - Метод
String getPattern()
возвращает ошибочное регулярное выражение.
String getMessage()
возвращает многострочную строку со значениями, возвращенными из предыдущих методов вместе с визуальным указанием на место синтаксической ошибки в шаблоне.
Что представляет собой синтаксическая ошибка? Вот пример:
java RegexDemo (?itree Treehouse
В данном случае мы забыли указать закрывающий метасимвол скобки ()
) во вложенном флаговом выражении. Вот что выводится в результате этой ошибки:
regex = (?itree
input = Treehouse
Неправильное регулярное выражение: Unknown inline modifier near index 3
(?itree
^
Описание: Unknown inline modifier
Позиция: 3
Неправильный шаблон: (?itree
Создание полезных приложений с регулярными выражениями при помощи API Regex
Регулярные выражения позволяют создавать приложения для обработки текста, обладающие большими возможностями. В этом разделе мы покажем вам два удобных приложения, которые, надеемся, побудят вас далее исследовать классы и методы API Regex. Во втором приложении вы познакомитесь с Lexan: библиотекой многоразового кода для выполнения лексического анализа.Регулярные выражения и документация
Документирование – одна из обязательных задач при разработке профессионально выполненного программного обеспечения. К счастью, регулярные выражения могут помочь вам со многими аспектами создания документации. Код в листинге 1 извлекает строки, содержащие однострочные и многострочные комментарии в стиле языка C, из исходного файла и записывает их в другой файл. Чтобы код работал, комментарии должны быть расположены в одной строке. Листинг 1. Извлечение комментариев
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
public class ExtCmnt
{
public static void main(String[] args)
{
if (args.length != 2)
{
System.err.println("Способ применения: java ExtCmnt infile outfile");
return;
}
Pattern p;
try
{
// Следующий шаблон определяет многострочные комментарии,
// располагающиеся в одной строке (например, /* одна строка */)
// и однострочные комментарии (например, // какая-то строка).
// Комментарий может располагаться в любом месте строки.
p = Pattern.compile(".*/\\*.*\\*/|.*//.*$");
}
catch (PatternSyntaxException pse)
{
System.err.printf("Синтаксическая ошибка в регулярном выражении: %s%n", pse.getMessage());
System.err.printf("Описание ошибки: %s%n", pse.getDescription());
System.err.printf("Позиция ошибки: %s%n", pse.getIndex());
System.err.printf("Ошибочный шаблон: %s%n", pse.getPattern());
return;
}
try (FileReader fr = new FileReader(args[0]);
BufferedReader br = new BufferedReader(fr);
FileWriter fw = new FileWriter(args[1]);
BufferedWriter bw = new BufferedWriter(fw))
{
Matcher m = p.matcher("");
String line;
while ((line = br.readLine()) != null)
{
m.reset(line);
if (m.matches()) /* Должна соответствовать вся строка */
{
bw.write(line);
bw.newLine();
}
}
}
catch (IOException ioe)
{
System.err.println(ioe.getMessage());
return;
}
}
}
Метод main()
из листинга 1 сначала проверяет правильность синтаксиса командной строки, после чего компилирует предназначенное для обнаружения одно- и многострочных комментариев регулярное выражение в объект класса Pattern
. Если не возникает исключения PatternSyntaxException
, метод main()
открывает исходный файл, создает целевой файл, получает сопоставитель для сопоставления каждой прочитанной строки с шаблоном, после чего читает исходный файл построчно. Для каждой строки выполняется сопоставление её с шаблоном комментария. В случае успеха, метод main()
записывает строку (с последующим символом новой строки) в целевой файл (мы рассмотрим логику файлового ввода/вывода в будущем учебном пособии Java 101).
Скомпилируйте листинг 1 следующим образом:
javac ExtCmnt.java
Выполните приложение с файлом ExtCmnt.java
в качестве входного:
java ExtCmnt ExtCmnt.java out
Вы должны получить в файле out следующие результаты:
// Следующий шаблон определяет многострочные комментарии,
// располагающиеся в одной строке (например, /* одна строка */)
// и однострочные комментарии (например, // какая-то строка).
// Комментарий может располагаться в любом месте строки.
p = Pattern.compile(".*/\\*.*\\*/|.*//.*$");
if (m.matches()) /* Должна соответствовать вся строка */
В строке шаблона .*/\\*.*\\*/|.*//.*$
, метасимвол вертикальной черты |
играет роль логического оператора ИЛИ, указывающего на необходимость сопоставителю использовать левый операнд из конструкции данного регулярного выражения для поиска соответствия в тексте сопоставителя. Если соответствий нет, сопоставитель использует правый операнд из конструкции данного регулярного выражения для еще одной попытки поиска (метасимволы скобок в захватываемой группе тоже формируют логический оператор).
Регулярные выражения в Java, часть 5
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ