java-regex_RU.ppt
- Количество слайдов: 24
Регулярные выражения в Java
Регулярные выражения • Регулярным выражением называется некоторый шаблон, который может быть применён к тексту(String, в Java) • Регулярное выражение либо соответствует(matches) тексту (или части текста), либо не соответствует ему – Если регулярное выражение соответствует части текста, то легко найти какой именно – Если регулярное выражение составное, тогда легко можно найти какая именно часть регулярного выражения какой именно части текста соответствует – Используя эту информацию, можно извлекать части текста и производить замены в тексте • Регулярные выражения очень удобный инструмент для обработки текста – Регулярные выражения часто используются для автоматической генерации Web страниц
Perl и Java • Язык программирования Perl широко используется в программирование на стороне сервера, потому что – Работа с текстом – большая доля для программирования на серверной стороне – Регулярные выражения встроены в синтаксис языка Perl • Начиная с версии Java 1. 4, в Java есть пакет, который работает с регулярными выражениями, java. util. regex – Регулярные выражения в Java и Perl похожи – Эта новая возможность во многом унаследована от обработки текстов в Java 1. 4 • Регулярные выражения в Java 1. 4 - обычный пакет, не нужно нового синтаксиса для поддержания их – Регулярные выражения в Java мощны, также как в Perl, но – Регулярные выражения удобнее, чем в Perl
Первый пример • Регулярное выражение "[a-z]+" выделяет последовательность из одного или более символов нижнего регистра [a-z] означает любой символ от a до z, включающий знак + означает “один или больше” • Предположим мы применяем этот шаблон к строке "Now is the time" – Существует три пути каким образом можно применить шаблон: • К целой строке: не пройдёт тестирование, потому что строка содержит отличные от символов алфавита в нижнем регистре • К началу строки: не сработает, поскольку строка не начинается с символа нижнего регистра • Поиск по всей строке: а вот это сработает и выдаст первое совпадение ow – Если применить повторно, найдут is, the, time, и fail
Так сделаем это на Java, I • Сперва нужно скомпилировать(compile) шаблон import java. util. regex. *; Pattern p = Pattern. compile("[a-z]+"); • Затем, нужно создать “выделитель” (matcher) для участка текста посылая сообщение шаблону Matcher m = p. matcher("Now is the time"); • На заметку: – Pattern и Matcher в пакете java. util. regex – Ни Pattern ни Matcher не имеют публичного конструктора; их нужно создавать используя методы класса Pattern – Выделитель (matcher) содержит информацию обо всём: шаблоне и тексте, к которому будем применять
Так сделаем это на Java, II • Пусть у нас есть выделитель m, – m. matches() возвращает true если шаблон соответствует всей входной текстовой строке, и false в противном случае – m. looking. At() возвращает true если шаблон соответствует началу текстовой строки, и false иначе – m. find() возвращает true если шаблон соответствует любой части текстовой строки, и false иначе • Если повторно вызвать метод, m. find() он продолжит искать с того места на котором остановился при предыдущем вызове • m. find() вернёт true столько раз, сколько вхождений шаблона в строку; после чего, он вернёт false • Когда m. find() возвращает false, выделитель m сбрасывается на начало строки (и может быть использован снова)
Нахождение выделенного • После успешного выделения, m. start() вернёт индекс первого найденного символа • После успешного выделения, m. end() возвращает индекс последнего символа, плюс один • Если попытка выделения не производилась, или была неуспешной, то m. start() и m. end() бросит ошибку Illegal. State. Exception – Это Runtime. Exception, вы не обязаны её обрабатывать • Может показаться странным, что m. end() возвращает индекс последнего элемента плюс один, но это потому что многие методы класса String требуют (удобно) – Например, "Now is the time". substring(m. start(), m. end()) вернёт как раз выделенную подстроку
Полный пример import java. util. regex. *; public class Regex. Test { public static void main(String args[]) { String pattern = "[a-z]+"; String text = "Now is the time"; Pattern p = Pattern. compile(pattern); Matcher m = p. matcher(text); while (m. find()) { System. out. print(text. substring(m. start(), m. end()) + "*"); } } } Результат: ow*is*the*time*
Дополнительные методы • Если m выделитель, тогда – m. replace. First(replacement) возвращает новую String где первая подстрока отвечающая шаблону заменена на replacement – m. replace. All(replacement) возвращает новую String где все подстроки отвечающие шаблону заменены на replacement – m. find(start. Index) ищет следующее вхождение шаблона, начиная от некоторого индекса – m. reset() сбрасывает выделитель – m. reset(new. Text) сбрасывает выделитель и даёт новый текст на “исследование” (который может быть String, String. Buffer, или Char. Buffer)
Некоторые простые шаблоны abc точная последовательность 3 -ёх символов [abc] любой один из трёх символов a, b, или c [^abc] любой символ кроме трёх a, b, или c (непосредственно внутри кв. скобки, ^ означает “нет, ” но в других случаях означает просто символ ^) [a-z] любой один символ от a до z, включительно [a-z. A-Z 0 -9] любой один символ или цифра
Последовательности и альтернативы • Если один шаблон следует за другим, или два шаблона следуют последовательно – Например, [A-Za-z]+[0 -9] выделит один или более символов алфавита, за которыми следует одна цифра • Вертикальная черта, |, используется для выбора альтернатив – Например, шаблон abc|xyz выделит либо abc, либо xyz
Некоторые предопределенные классы символов. любой одиночный символ, кроме символа конца строки d цирфа: [0 -9] D не-цифра: [^0 -9] s знак пробела (любой): [ tnx 0 Bfr] S не знак пробела (любого): [^s] w буква слова: [a-z. A-Z_0 -9] W не буква слова: [^w] Замечание пробел. Пробелы важны в регулярных выражениях!
Граничные выделители • Эти шаблоны выделяют пустые строки или спец позиции: ^ начало строки $ конец строки b граница слова B не граница слова A начало ввода (может быть несколько строк) Z конец ввода, кроме символа терминации, если есть z конец ввода G конец предыдущего выделения
Жадные квантификаторы (Термин “жадный” будет объяснён позднее) Предположим X представляет некоторый шаблон X? опционально, X случается однажды или вообще не случается X* X произвольное число раз X+ X случается один или больше раз X{n} X случается ровно n раз X{n, } X случается n или больше раз X{n, m} X случается по крайне мере n но не более чем m раз Заметим, что все квантификаторы постфиксные операции, то есть идут после операнда
Типы квантификаторов • Жадные будет выделять пока может, и отступает назад, только если очень нужно – We’ll do examples in a moment • Расслабленные выделяют настолько мало, сколько смогут, берут больше – если очень нужно – Расслабить “жадные” можно символом ? : X? ? X*? X+? X{n}? X{n, m}? • Эгоистичные выделяют так много как могут и, никогда не отдают добро – Сделать эгоистичными можно прибавлением +: X? + X*+ X++ X{n}+ X{n, m}+
Примеры квантификаторов • Пусть есть следующий текст aardvark – Используем шаблон a*ardvark (a* жадный): • a* выделит aa, но затем должен быть ardvark • a* отдаст для “общего дела” одну a, и шаблон (ardvark) успешно отработает – Используем a*? ardvark (a*? расслабленный): • a*? полениться что-то выделять (строка null), но тогда не подходит ardvark • a*? согласится взять первую букву a, и шаблон (ardvark) успешно отработает – Используем шаблон a*+ardvark (a*+ эгоистичен): • a*+ выделит aa, и будет сидеть на них до конца, так ardvark никогда не совпадёт и шаблон не заработает
Захваченные группы • В регулярных выражениях, круглые скобки используются для группировки, их также можно назвать захваты (придержать для дальнейшего использования) всё выделенное частью шаблона – Например: ([a-z. A-Z]*)([0 -9]*) выделяет любое число букв, за которыми следует любое число цифр – Если выделение будет успешным, 1 содержит буквы и 2 содержит цифры – В дополнение, то, что выделено по всему шаблону • Захватывающие группы нумеруются по открытым скобкам слева направо: – ((A)(B(C))) 12 3 4 = 1 = ((A)(B(C))), 2 = (A), 3 = (B(C)), 4 = (C) • Пример: ([a-z. A-Z])1 выделяет двойные символы, как letter
Захваченные группы в Java • Если m выделитель который успешно выполнился, тогда – m. group(n) возвратит String соответствующий захваченной группе n • Это может быть пустая строка • Это может быть null если весь шаблон выполняется, но эта группа ничему не соответствует – m. group() возвращает String соответствующий всему шаблону (так же как и m. group(0)) • Это может быть пустая строка • Если m не соответствует(или не было попыток), этот метод бросает исключение Illegal. State. Exception
Пример использования захватывающих групп • Предположим word соответствует слову в англ. • Также предположим, что мы хотим передвинуть все согласные из начала слова word (если есть) в конец слова (так string станет ingstr) – Pattern p = Pattern. compile("([^aeiou]*)(. *)"); Matcher m = p. matcher(word); if (m. matches()) { System. out. println(m. group(2) + m. group(1)); } • Заметим использование (. *) для индикации “все остальные символы”
Двойные бэкслеши • Бэкслеши имеют специальный смысл в регулярных выражениях; например, b означает границу слова • Бэкслеши имеют специальное значение в Java; например, b означает символ пробела • Сперва применяются правила языка Java! • Если написать "b[a-z]+b" получится строка с двумя пробелами внутри – это не то что вы хотели! • Запомните, вы можете использовать двойные бэкслешм, так "\b[a-z]+\b" даёт правильную строку Запомните: если вы читаете строку где-то, которая не работает – вы должны проверить те ли в ней символы
Обозначение метасимволов • Множество специальных символов – обычные, квадратные, фигурные скобки, звездочка, знак плюса и т. д. —используются в регулярных выражениях; их называют метасимволы • Предположим вы хотите найти a* (a со *) – "a*"; не работает; поскольку значит “ноль или больше a” – "a*"; не работает; звездочку не нужно выделять бэкслешем (см константы Java String), Java проигнорирует знак – "a\*" работает; это три символа a, , * • Чтобы жизнь мёдом не казалась, в регулярных выражениях запрещено выделять не-метасимволы
Пробелы • Одно можно сказать о пробелах (пустышках) в регулярных выражениях, но это важно: – Пробелы важны! • Пробел отвечает за пробел—когда вы вставляете пробел в шаблон, это означает, что вы ищите пробел в тексте! • Очень очень плохая идея вставлять пробелы в регулярные выражения, чтобы они “читались лучше”…
Думайте в регулярных выражениях • Регулярные выражения не просто использовать поначалу – Это поток закорючек без слов – Может показаться простым по отдельности – но вместе сущий ужас и хаос – Регулярные выражение – язык программирования в миниатюре • Это другая, отличная от Java парадигма, и требует от вас учиться по новым шаблонам – В Java вы не можете просто использоватьa регулярные выражения; создайте Patterns и Matchers – Синтаксис Java для работы со строками не помогает, однако • Несмотря на это, регулярные выражения очень мощный и удобный инструмент обработки строк, что окупает все усилия по их изучению
Конец