Урок 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>

Обратите внимание, что слеш мы экранируем с помощью обратного слеша, чтобы он воспринимался как простой текст.

Фух. Тема действительно достаточно сложная, тут нужна практика. Возможно я что-то делаю не вполне оптимально и можно составить другие, более правильные регулярные выражения, но я такой же самоучка как и вы, поэтому не судите строго, а лучше поделитесь своими вариантами в комментариях. Также, если что-то не понятно — комментарии и страница контактов к вашим услугам.

Комментарии:

  1. Василий — 25.02.2015 19:21

    Прелестно! Очень понравилось то, что все легко и в доступной форме изложено! Бери и пользуйся!Спасибо автору!!!

  2. viktor — 29.05.2015 01:47

    Видимо мне долго парится прийдётся!!!

  3. Юсупбай — 15.06.2015 11:48

    Респект создателям сайта Спс большое!!!!!

  4. Хакер — 07.12.2015 23:06

    Уроки очень легкие и классные. Спасибо автору!

  5. Владимир — 08.02.2016 16:38

    Не разъясняется смысл вопросительного знака после звездочки. Это значит что регулярное выражение не жадное (not greedy).

  6. Majid — 14.02.2016 15:10

    спасибо админ,..как можно создать сайт на php

  7. вася — 30.03.2017 14:56

    где следующие уроки?

  8. Васъя — 05.10.2017 18:36

    Ужос, одмен уже 2 коммента потер, кажется это любовь ( ͡° ͜ʖ ͡°)

Добавить комментарий