Администрирование ОС
[2]
Вопросы администрирования ОС
|
Виртуализация ОС
[2]
Технологии виртуализации
|
Программирование
[19]
Вопросы программирования и проектирования (OpenSource, Java, DSP, Portal, SSO, Identity, Collaboration, WebSerives, ORM, RDBMS, SOA, SOA Secutity etc.)
|
Общие Вопросы
[8]
Общие жизненные вопросы...
|
Программирование Java
[15]
Программирование Java - технология Java SE
|
Программирование Java EE
[1]
Программирование Java - технология Java EE
|
Обучение программированию
[1]
Обучение программированию - курсы, источники в интернете, учебные материалы
|
Oracle
[5]
Oracle, Java, jDeveloper, Oracle Application Express, Oracle Database Express Edition
|
« Ноябрь 2012 » | ||||||
Пн | Вт | Ср | Чт | Пт | Сб | Вс |
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 |
19:31 Введение в Java-программирование: Часть 2. Конструкции реальных приложений. Регулярные выражения. |
http://www.ibm.com/developerworks/ru/edu/j-introtojava2/section8.html Регулярное выражение - это, по сути, модель, описывающая набор строк, составленных по одной и той же схеме. Программистам, работающим с Perl, модель синтаксиса регулярных выражений (regex) языка Java должна показаться знакомой. Но тем, кто не привык к нему, этот синтаксис может показаться странным. В этом разделе описываются принципы работы с использованием регулярных выражений в программах на языке Java.API регулярных выражений Следующий набор строк имеет нечто общее: A string A longer string A much longer string Заметьте, что каждая из этих строк начинается с буквы а и заканчивается словом string. API регулярных выражений Java (см. Ресурсы) помогает выявить такие элементы, увидеть в них общую модель и делать интересные вещи с использованием полученной информации. API регулярных выражений состоит из трех основных классов, которыми вы будете пользоваться очень часто: Pattern описывает модель строки. Matcher проверяет строку на соответствие модели. PatternSyntaxException указывает на что-то неприемлемое в той модели, которую вы пытаетесь определить. Скоро мы начнем работать над моделью простых регулярных выражений, которая использует эти классы. Однако сначала рассмотрим синтаксис модели регулярных выражений. В начало Синтаксис модели регулярных выражений Модель регулярных выражений описывает структуру строк, которую выражение пытается обнаружить во входной строке. Регулярные выражения в ней могут выглядеть немного странно. Однако как только вы освоите синтаксис, их станет легче расшифровать. В таблице 2 приведены некоторые наиболее распространенные конструкции регулярных выражений, которые применяются для моделирования строк: Таблица 2. Распространенные конструкции регулярных выражений Конструкция Regex Что считается совпадением . Любой символ ? Ноль (0) или одно (1)повторение предшествующего * Ноль (0) или более повторений предшествующего + Одно (1) или более повторений предшествующего [] Диапазон символов или цифр ^ Отрицание последующего (то есть, "не что-то") \d Любая цифра (иначе, [0-9]) \D Любой нецифровой символ (иначе, [^0-9]) \s Любой символ-разделитель (иначе, [\n\t\f\r]) \S Любой символ, отличный от разделителей (иначе, [^\n\t\f\r]) \w Любая буква или цифра (иначе, [A-Za-Z_0-9]) \W Любой знак, отличный от буквы или цифры (иначе, [^\w]) Первые конструкции называются квантификаторами, поскольку они определяют количество того, что им предшествует. Конструкции типа \d - это определенные классы символов. Любой символ, который не имеет специального значения в шаблоне, является буквальным и соответствует самому себе. Поиск по модели Вооружившись синтаксисом моделей из таблицы 2, можно выполнить простой пример, приведенный в листинге 19, используя классы API регулярных выражений Java. Листинг 19. Поиск по модели регулярных выражений Pattern pattern = Pattern.compile("a.*string"); Matcher matcher = pattern.matcher("a string"); boolean didMatch = matcher.matches(); Logger.getAnonymousLogger().info (didMatch); int patternStartIndex = matcher.start(); Logger.getAnonymousLogger().info (patternStartIndex); int patternEndIndex = matcher.end(); Logger.getAnonymousLogger().info (patternEndIndex); Сначала создается класс Pattern. Это делается с помощью вызова статического метода compile() объекта Pattern со строковым литералом, который представляет собой модель, соответствие которой мы ищем. Этот литерал использует синтаксис модели регулярных выражений. Обычным языком модель, приведенную в данном примере, можно описать следующим образом: Найти строку вида: буква а, за которой следуют ноль или более символов, а за ними - строка string. Методы сравнения Затем в листинге 19 вызывается метод matcher() объекта Pattern. Этот вызов создает экземпляр Matcher. Matcher проверяет переданную ему строку на соответствие модели, использованной при создании объекта Pattern. Каждая строка на языке Java – это индексированная коллекция символов, начиная с 0-го и заканчивая символом с индексом "длина строки минус единица". Matcher анализирует строку, начиная с 0-го символа, в поисках совпадений с моделью. После завершения этого процесса Matcher содержит информацию о найденных (или не найденных) совпадениях в строке ввода. Доступ к этой информации можно получить, вызывая различные методы Matcher: matches() сообщает, совпадает ли с моделью вся входная последовательность; start() указывает значение индекса в строке, с которого начинается совпадение; end() указывает значение индекса в строке, на котором совпадение заканчивается, плюс единица. Код, приведенный в листинге 19, находит одно совпадение, с 0-й по 7-ю позицию. Следовательно, вызов matches() возвращает значение true, вызов start() возвращает значение 0, a вызов end() возвращает значение 8. lookingAt() и matches() Если бы в строке было больше элементов, чем в модели поиска, вместо matches() можно было бы использовать метод lookingAt(). lookingAt() ищет совпадения подстрок с данной моделью. Например, рассмотрим следующую строку: Here is a string with more than just the pattern. Если искать по модели a.*string и использовать lookingAt(), мы получим совпадение. Но метод matches() возвратил бы значение false, так как в строке есть не только то, что указано в модели. В начало Сложные модели регулярных выражений Простой поиск по классам регулярных выражений производить легко, но с API регулярных выражений можно делать и довольно сложные вещи. Вики, как вы наверняка знаете, это Web-система, которая позволяет пользователям редактировать страницы. Вики почти исключительно основаны на регулярных выражениях. Их содержание зависит строки, введенной пользователем, которая анализируется и форматируется с использованием регулярных выражений. Любой пользователь может дать ссылку на другую тему, введя wiki-слово, которое, как правило, представляет собой последовательности соединенных слов, каждое из которых начинается с прописной буквы, например: MyWikiWord Зная это, рассмотрим следующую строку: Here is a WikiWord followed by AnotherWikiWord, then YetAnotherWikiWord. В этой строке можно искать вики-слова с помощью модели регулярных выражений: [A-Z][a-z]*([A-Z][a-z]*)+ И вот код для поиска wiki-слов: String input = "Here is a WikiWord followed by AnotherWikiWord, then SomeWikiWord."; Pattern pattern = Pattern.compile("[A-Z][a-z]*([A-Z][a-z]*)+"); Matcher matcher = pattern.matcher(input); while (matcher.find()) { Logger.getAnonymousLogger().info("Found this wiki word: " + matcher.group()); } Выполнив этот код, вы должны увидеть на консоли три wiki-слова. Замена строк Поиск совпадений полезен, но и после того как совпадение найдено со строками можно что-то делать. Одни строки можно заменять другими, как текст в текстовом редакторе. В Matcher есть несколько методов для замены элементов строк: ReplaceAll() заменяет все совпадения указанной строкой; replaceFirst() заменяет указанной строкой только первое совпадение. Использовать методы замены Matcher легко: String input = "Here is a WikiWord followed by AnotherWikiWord, then SomeWikiWord."; Pattern pattern = Pattern.compile("[A-Z][a-z]*([A-Z][a-z]*)+"); Matcher matcher = pattern.matcher(input); Logger.getAnonymousLogger().info("Before: " + input); String result = matcher.replaceAll("replacement"); Logger.getAnonymousLogger().info("After: " + result); Этот код находит wiki-слова, как и прежде. Обнаружив совпадение, Matcher заменяет wiki-слово другим. Выполнив этот код, вы должны увидеть на консоли следующее: Before: Here is WikiWord followed by AnotherWikiWord, then SomeWikiWord. After: Here is replacement followed by replacement, then replacement. При использовании replaceFirst() вы бы увидели: Before: Here is a WikiWord followed by AnotherWikiWord, then SomeWikiWord. After: Here is a replacement followed by AnotherWikiWord, then SomeWikiWord. В начало Сопоставление групп и манипулирование ими При поиске совпадений с моделью регулярного выражения можно получить информацию о найденном. Мы видели, как это делается с помощью методов start() и end() объекта Matcher. Но на совпадения можно ссылаться и с помощью групп. В каждой модели, как правило, создаются группы – для этого отдельные ее части заключаются в круглые скобки. Группы нумеруются слева направо, начиная с 1 (группа 0 соответствует всему совпадению). Код, приведенный в листинге 20, заменяет каждое вики-слово строкой, которая "обертывает" слово: Листинг 20. Совпадение групп String input = "Here is a WikiWord followed by AnotherWikiWord, then SomeWikiWord."; Pattern pattern = Pattern.compile("[A-Z][a-z]*([A-Z][a-z]*)+"); Matcher matcher = pattern.matcher(input); Logger.getAnonymousLogger().info("Before: " + input); String result = matcher.replaceAll("blah$0blah"); Logger.getAnonymousLogger().info("After: " + result); Выполнив этот код, вы получите следующий результат: Before: Here is a WikiWord followed by AnotherWikiWord, then SomeWikiWord. After: Here is a blahWikiWordblah followed by blahAnotherWikiWordblah, then blahSomeWikiWordblah. Другой подход к совпадению групп В листинге 20 делается ссылка на все совпадение путем включения в строку замены $0. Любая часть заменяющей строки вида $int относится к группе, указанной целым числом (так, $1 указывает на группу 1 и т.п.). Другими словами, запись $0 эквивалентна matcher.group(0);. Той же цели можно было бы достичь с помощью некоторых других методов. Вместо вызова replaceAll(), можно сделать следующее: StringBuffer buffer = new StringBuffer(); while (matcher.find()) { matcher.appendReplacement(buffer, "blah$0blah"); } matcher.appendTail(buffer); Logger.getAnonymousLogger().info("After: " + buffer.toString()); И вы получите тот же результат: Before: Here is a WikiWord followed by AnotherWikiWord, then SomeWikiWord. After: Here is a blahWikiWordblah followed by blahAnotherWikiWordblah, then blahSomeWikiWordblah. |
|
Всего комментариев: 0 | |