Урок 21. Регулярные выражения в PHP
В практических уроках (один, два) я показал вам пример использования регулярных выражений для нахождения определенных кусков исходного кода страницы. Сейчас же мы с вами научимся писать их самостоятельно. Данный навык поможет писать парсеры, очищать текст от ненужных фрагментов, искать нужные части в больших объемах текста и так далее.
Эта тема довольно непроста, но я постараюсь в краткой форме осветить самые важные моменты. Не знаю насколько это у меня получится, но надеюсь польза от урока будет.
Итак, начнем с того, что для работы с регулярными выражениями в PHP существует несколько функций, но чаще всего используются три:
- preg_replace — поиск и замена подходящего по регулярному выражению текста;
- preg_match — просто поиск по регулярке;
- preg_split — поиск и разделение текста.
По крайней мере, в предыдущих уроках мы пользовались именно ими. Вернее, вместо preg_match был preg_match_all, но это по сути тоже самое, только последний не прерывает поиск после первого нахождения. То есть, если использовать preg_match, то мы не найдем все вхождения, а лишь только первое.
Выбор в какой ситуации какую функцию использовать довольно простой. Нужно заменить — используем replace, как в случае когда нам нужно было удалить ненужные части кода страницы, помните?
$page = preg_replace('/<input type=checkbox.*?[>^]/i', '', $page); $page = preg_replace('/<label.*?[>^]/i', '', $page); $page = str_replace('</label>', '', $page);
Первый параметр функции — регулярка, определяющая Что мы ищем. Второй — на что заменяем. Третий — Где ищем. Следовательно, здесь мы брали переменную $page и присваивали ей результат функции preg_replace где искали все input type=checkbox, а также открывающиеся и закрывающиеся label. Заменяли их на », то есть просто удаляли. Надеюсь тут все ясно. К разбору самого выражения (первого параметра функции) мы перейдем чуть позже.
Был и пример использования preg_match_all, который пригодился для поиска всех ссылок в оставшемся тексте. Ссылки нам тогда понадобились потому, что именно в них были заключены ключевые слова, которые мы парсили. Вот что было:
preg_match_all("/<a[^<>]+?>(.*?)<\/a>/uis",$page,$ok); for ($j=0; $j<count($ok[1]); $j++) { echo "<li>".$ok[1][$j]."</li>"; }
Первым параметром опять же является регулярка, чтобы найти все ссылки, которые, естественно заключены в тег «a» (если не дружите с html разметкой, то почитайте мои уроки). Второй — переменная в которой содержится текст, по которому будет происходить поиск. Третьим параметром поставлена переменная, в которую помещается результат — $ok. После этого лишь остается пройтись по всем нужным элементам $ok, чтобы достать нужные нам ключевые лова. Отдельно нужно сказать, что на выходе мы получаем многомерный массив. Именно поэтому мы выводили его таким сложным способом: $ok[1][$j]. Чтобы посмотреть структуру массива воспользуйтесь функцией ниже и вы все поймете.
print_r($ok);
Вот, вроде бы, с функциями, которые мы использовали для работы, разобрались. Теперь остается только научиться писать эти самые регулярные выражения, которые являются первым параметром каждого из этих методов. Переходим к самому важному.
Как же писать регулярки
Для начала разберем основные конструкции. У выражений есть опции. Они задаются одной буквой и пишутся в конце, перед ними ставится слеш.
Кроме этого поддерживаются следующие метасимволы:
Метасимволы, в свою очередь, могут иметь модификаторы:
Что же, теперь можем перейти к разбору наших регулярок из прошлого урока. Опираясь на таблички выше попробуем понять, что же у нас есть. Вот выражение:
/<input type=checkbox.*?[>^]/i
Первый и последний слеши «/» показывают, что внутри них идет регулярное выражение. При этом, после последнего мы поставили «i», это опция, как в первой таблице — не учитывать регистр. Внутри слешей сама регулярка. Она начинается со знака меньше и тега input, а также все, что идет потом, до знака точки — простой текст, который нужно искать. А вот сама точка, и символы после нее — это уже интереснее. В данном случае, конструкция «.*?» означает любую последовательность символов. То есть, если объединить просто текст и данную конструкцию, то мы выберем весь текст после первого вхождения и до конца. Чтобы остановиться нужно встретить либо закрывающийся html тег «больше», либо символ начала новой строки. Эта конструкция как раз нам и дает такую возможность:
[>^]
Символы в квадратных скобках как бы соединены логическим ИЛИ. Концом является знак «больше» ИЛИ начало строки.
Вот и все выражение, в нем мы задали условие начала, середину и условие окончания. Не трудно, правда? Вот иллюстрация для пущей наглядности:
Давайте разберем еще одно, чтобы все закрепить. Им мы искали ссылки:
/<a[^<>]+?>(.*?)<\/a>/uis
Читаем выражение. Опять же, сначала отбрасываем слеши и опции. Флаги «uis» понятны, за исключением «u», который я не описывал — он показывает, что мы используем кодировку Юникод. Остается не так много. Началом является тег «a», который открывается, затем идет класс
[^<>]
который обозначает НЕ больше или меньше (открывающий и закрывающийся html теги), то есть любые символы в данном случае. К классу добавляется «+?», которые означают, что этот класс будет присутствовать 1 или большее число раз (но хотя бы 1 раз точно). И потом идет закрывающийся html тег для тега «a». Внутри ссылки есть текст, который задается группой
(.*?)
Ведь мы не знаем что там будет за текст, поэтому определяем такую группу. И в конце закрывающийся тег «a»:
<\/a>
Обратите внимание, что слеш мы экранируем с помощью обратного слеша, чтобы он воспринимался как простой текст.
Фух. Тема действительно достаточно сложная, тут нужна практика. Возможно я что-то делаю не вполне оптимально и можно составить другие, более правильные регулярные выражения, но я такой же самоучка как и вы, поэтому не судите строго, а лучше поделитесь своими вариантами в комментариях. Также, если что-то не понятно — комментарии и страница контактов к вашим услугам.
Комментарии:
Прелестно! Очень понравилось то, что все легко и в доступной форме изложено! Бери и пользуйся!Спасибо автору!!!
Видимо мне долго парится прийдётся!!!
Респект создателям сайта Спс большое!!!!!
Уроки очень легкие и классные. Спасибо автору!
Не разъясняется смысл вопросительного знака после звездочки. Это значит что регулярное выражение не жадное (not greedy).
спасибо админ,..как можно создать сайт на php
где следующие уроки?
Одмен потер уже 3 мои коммента, в который не было ни мата не оскорблений, довольно обидно ( ̄’﹃ ̄’)