Синтаксис регулярных выражений
Строгое определение регулярного выражения выглядит довольно громоздко. Начнем с неформального описания.
Регулярное выражение представляет собой строку. Эта строка состоит из собственно регулярного выражения (шаблона), выделенного с помощью специального символа разделителя (это могут быть символы «/» , «|», «{«, «!» и т.п ) и модификатора, влияющего на способ обработки РВ.
В дальнейшем это описание будет расширено.
Например, в регулярном выражении /\d{3}-\d{2}-\d{2}/m символ «/»является разделителем, \d{3}-\d{2}-\d{2} – непосредственно регулярное выражение (шаблон), а m – модификатор.
Мощь регулярных выражений порождена в основе своей их способностью включать в шаблон альтернативы и повторения. Они кодируются в шаблоне с помощью метасимволов. Метасимвол отличается от любого другого символа тем, что имеет специальное значение.
Одним из основных метасимволов является обратный слэш «\». Он меняет тип символа, следующего за ним, на противоположный, т.е. если это был обычный символ, то он МОЖЕТ превратиться в метасимвол, если это был метасимвол, то он теряет свое специальное значение и становится обычным символом (это нужно для того, чтобы вставлять в текст специальные символы как обычные). Например, символ d в обычном режиме не имеет никаких специальных значений, но \d есть метасимвол, означающий «любая цифра». Символ «.» в обычном режиме означает «любой единичный символ», а «\.» означает просто точку.
Другое назначение обратного слэша – кодирование непечатных символов, таких как :
\n – cимвол перевода строки;
\e – символ escape;
\t – cимвол табуляции;
\xhh – символ в шестнадцатеричном коде, например \x41 есть буква A и т.д.
Еще одно назначение обратного слэша – обозначение генерируемых символьных типов, таких как:
\d – любая десятичная цифра (0-9);
\D – любой символ, не являющийся десятичной цифрой;
\s – любой пустой символ (пробел или табуляция);
\S – любой символ, не являющийся пустым;
\w – символ, используемый для написания Perl-слов (это буквы, цифры и символ подчеркивания), так называемый «словарный символ»;
\W – несловарный символ (все символы, кроме определяемых \w).
Что имеется в виду под «символьным типом»? Просто каждый метасимвол принимает значение (одно) из класса возможных значений, заданных автоматически или вручную. Символьные типы, задаваемые пользователем, описываются с помощью квадратных скобок (подробнее об этом позже). Выше приведены символьные типы, диапазон значений которых заранее определен языком программирования.
Пример использования приведенных выше метасимволов:
/\d\d\d plus \d is \w\w\w/
Это РВ означает: трехзначное число, за которым следует подстрока plus, любая цифра, затем is и слово из трех словарных символов. В частности, данному РВ удовлетворяют строки: «123 plus 3 is sum», «213 plus 4 is 217».
Вообще различают два множества метасимволов: те, что распознаются в любом месте шаблона, за исключением внутренности квадратных скобок, и те, что распознаются внутри квадратных скобок.
Квадратные скобки [ ] применяются для описания подмножеств и внутри регулярного выражения рассматриваются как один символ, который может принимать значения, перечисленные внутри этих скобок. Однако если первым символом внутри скобок является ^, то значением символьного класса могут быть только символы, НЕ перечисленные внутри скобок.
Примеры:
- Символьный класс [абвгд] задает один из символов а, б, в, г, д, а класс [^абвгд] задает любой символ, кроме а, б, в, г, д.
- Если написать [2бул]ки], то это выражение интерпретируется как один из символов 2, б, у, л, за которым следует строка ки], потому что первая встретившаяся закрывающая квадратная скобка (разбор происходит слева направо) заканчивает определение символьного класса. То есть это РВ совпадет с одной из строк 2ки], бки], уки] или лки].
- С помощью РВ [0-9А-Яа-я] можно задать любую букву или цифру.
Метасимволы, распознаваемые вне квадратных скобок, можно разделить на группы следующим образом: определяющие положение искомого текста в строке, связанные с подвыражениями, ограничивающие символьный класс, квантификаторы и перечисление альтернатив.
Регулярное выражение /\d\d/ m может быть сопоставлено следующим подстрокам: 11, 22, 33. Если в начале РВ стоит ^, то совпадения ищутся в начале строки, поэтому выражение /^\d\d/m найдет только 11.
Когда в конце РВ стоит знак доллара $, поиск производится в конце строки, поэтому выражение /\d\d$/m найдет только 33.
Шаблону же /^\d\d\d$/ будет удовлетворять строка, целиком состоящая из трехзначного числа (т.е. она и начинается и заканчивается этим числом).
<? //считываем файл в строку $str = file_get_contents('1.htm'); $pattern = "!^<[^/]+>!mU"; // осуществляем поиск $n = preg_match_all ($pattern, $str, $res); // выводим результаты for ($i=0;$i<$n;$i++) echo htmlspecialchars($res[0][$i]). "<br>"; ?>
\ | Переходный символ со множеством назначений |
^ | Объявляет начало объекта (или строки в многострочном режиме). То есть этот символ определяет, что искомый текст должен находиться в начале строки. Альтернатива: «\A» |
$ | Объявляет конец объекта (или строки в многострочном режиме). То есть этот символ определяет, что искомый текст должен находиться в конце строки. Альтернативы: «\Z», «\z» |
. | Совпадает с любым символом, кроме символа перевода строки (по умолчанию) |
[ | Начинает определение символьного класса |
] | Заканчивает определение символьного класса |
| | Разделяет перечисление альтернативных вариантов |
( | Начинает подшаблон регулярное (подвыражение) |
) | Заканчивает подшаблон |
? | Расширяет значение «(», квантификаторов 0 или 1, и квантификатор минимизации |
* | 0 или больше повторений (квантификатор) |
+ | 1 или больше повторений (квантификатор) |
{ | Начинает минимальный/максимальный квантификатор |
} | Заканчивает минимальный/максимальный квантификатор |
Шаблон ограничен восклицательными знаками. Первая «^» значит, что мы ищем совпадения в начале строк, потом идет символ «<» – его и ищем в строке, после него должно идти все, что угодно, кроме обратного слэша (конструкция «[^\]» ), «+» говорит, что стоящий перед ним символ повторяется один и более раз и заканчивается все это символом «>». Таким образом, выделяются все теги в начале строк.
<? //считываем файл в строку $str = file_get_contents('1.htm'); $pattern = "!\s[А-Яа-я]+". "\s([А-Я]\.\s*)([А-Я]\.\s*)$!m"; // шаблон ограничен восклицатель- // ными знаками, m – модификатор, // включающий многострочный режим // первый \s означает, что перед // фамилией должен идти пустой // символ (например, пробел) // [А-Яа-я] задает одну из букв // алфавита в любом регистре,а в // комбинации со знаком плюс // определяет,что эта буква // повторяется один и более // раз следующий \s означает, что // между фамилией и инициалами // должен быть пробел // Далее идет подвыражение, // определяющее инициалы. // Это буква от А до Я, после // которой стоит точка ('\.') // Экранируем точку, чтобы // избавиться от ее специального // значения. После буквы с точкой // может идти или не идти пробел // или несколько. Вся конструкция // повторяется минимум два раза. // Последний символ $ означает, // что фамилия с инициалами // должны находиться в конце // строки. //осуществляем поиск $n = preg_match_all ($pattern, $str, $res); // выводим результаты for ($i=0;$i<$n;$i++) echo htmlspecialchars($res[0][$i]). "<br>"; ?>
Примеры ( | и .)
- Пусть имеется некий текст. Нам нужно найти всех упомянутых в нем людей со званиями.
<? $str = "Доцент Смирнов совершил". "открытие. Его учителем была ". "профессор Иванова. ". "Этим открытием Смирнов ". "завоевал себе степень ". "доктора. Раньше он был ". "только кандидат."; $pattern = "/(профессор|доцент)". "\s[А-Яа-я]+(\s|\.)/i"; // осуществляем поиск $n = preg_match_all ($pattern, $str, $res); // выводим результаты for ($i=0;$i<$n;$i++) echo htmlspecialchars($res[0][$i]). "<br>"; ?>
Метасимвол прямая черта « | » позволяет задавать альтернативные варианты. В примере мы хотели найти всех профессоров или доцентов. Для этого было создано подвыражение «(профессор|доцент)». После звания через пробел фамилия человека, которому оно принадлежит, – для этого существует комбинация «\s[А-Яа-я]+». После фамилии идет либо опять пробел, либо точка, если это конец предложения. Получаем опять два альтернативных варианта: «(\s|\.)» (здесь точка экранируется обратным слэшем, чтобы она понималась как обычная точка, без специального значения).