Регулярное выражение PHP для поиска всех ссылок

Содержание материала:

Популярные примеры работы регулярных выражений в PHP

Вопросов по данной теме уйма. И я решил создать свою подборку регулярных выражений. Думаю многим поможет!

Для справки.
. — (точка) соответствует любому символу.
<> — (фигурные скобки) нужны для обозначения количества необходимых символов. Например, w <3>— три буквы w подряд. Также есть диапозон z<2,5>, то есть z может повторяться от 2 до 5 раз.
| — (вертикальная черта) логическое или в регулярных выражениях.
\n — перевод строки
\r — так же перевод строки
\t — табуляция
\d — цифра
\D — только не цифра
\s — пробел
\S — только не пробел
\w — все буквы, цифры и знак подчеркивания «_»
\W — только не буква, цифра или подчеркивание
Модификаторы в конце выражения
/i — делает поиск по выражению регистронезависимым. Нет разницы между заглавным и прописным символом
/U — модификатор указывает на то, что результатом поиска должен быть самый короткий отрывок, удовлетворяющий маске поиска. Рекомендую всегда использовать данный модификатор
/m — этот модификатор позволяет искать отрезок текста только внутри одной строки
/s — поиск идёт всему тексту, не обращая внимания на переносы строк
/x — игнорируются пробельные символы, в том числе символы табуляции и перевода строки

Примеры preg_replace PHP

1. Удаляем определённую ссылку в переменной text

2. Удаляем комментарии в переменной text

3. Удаляем спецсимволы

4. Удаляем всё, что между

5. Удаляем всё, что между

6. Удаляем конкретные символы из строки

7. Удаляем пробелы по бокам строки и обычные пробелы

8. Удаляем лишние переводы строк и переносы

9. Удаляем расширения в названиях файлов

10. Создаём функцию обработки текста

11. Найти содержимое определённого тега и вставить его в другие теги

12. Удаляем многократно повторяющиеся знаки препинания (например, . или . )

13. Добавить или убрать текст в начале или конце переменной с текстом

14. Находим все http:// и заменяем на ссылки

15. Удаление GET-параметров из URL

16. Добавить тег br в начало или конец строк

17. Как конвертировать html в текст

18. Как разобрать email и сделать ссылку

Примеры preg_match PHP

1. проверка mail адреса на корректность

2. Найти mail адреса в тексте

3. Является ли переменная числом, длиной от 13 до 16 символов (проверка кредитной карты)

4. Проверка имени файла

Программы (exe, xpi, . )

Изображения (jpg, png, . )

5. Ищем в тексте мобильные телефоны РФ

6. Состоит ли строка только из букв, цифр и _, длиной от 8 до 20 символов:

7. Есть ли в строке идущие подряд символы, не менее 3-х символов подряд (типа абвгДДДеё, но не ааббаабб):

8. Поиск в разных частях строки конструкции:

9. Проверки на тип браузера. Возвращает true если browser = Netscape 2, 3 or MSIE 3.

Примеры ereg PHP

1. Проверка mail адреса в тексте

PHP регулярное выражение для поиска ссылок

Поэтому я сейчас работаю над регулярным выражением, которое будет использоваться на форуме, который также имеет поддержку bbcode. Предполагается, что это регулярное выражение перехватывает все ссылки, начинающиеся с https, http и www, и делает их ссылками.

В настоящее время он перехватывает все https и http, но не www. И я не могу понять, как получить те, которые начинаются с www.

Также имейте в виду, что если ссылка уже находится внутри bbcode, она не должна быть перехвачена в этом регулярном выражении.

Парсинг сайтов регулярными выражениями PHP

Парсинг сайтов

Для того, чтобы спарсить страницу сайта (то есть разобрать ее HTML код), ее для начала следует получить. А затем уже полученный код можно разобрать с помощью регулярных выражений и, либо каким-то образом его проанализировать, либо сохранить в базу данных, либо и то, и другое.

Получение страниц сайтов с помощью file_get_contents

Итак, для начала давайте поучимся получать страницы сайтов в переменную PHP. Это делается с помощью функции file_get_contents, которая чаще всего используется для получения данных из файла, однако, может быть использована для получения страницы сайта — если передать ей параметром не путь к файлу, а url страницы сайта.

Учтите, что эта функция не идеальна и существует более мощный аналог — библиотека CURL, которая позволяет работать с куками, с заголовками, позволяет отправлять формы и переходить по редиректам. Все это file_get_contents делать не умеет, однако для начала нам сойдет и она, а работу с CURL мы разберем в следующем уроке.

Итак, давайте для примера получим главную страницу моего сайта и выведем ее на экран (сделайте это):

Что вы получите в результате: у себя на экране вы увидите страницу моего сайта, однако, скорее всего без CSS стилей и картинок (будут ли работать CSS и картинки — зависит от сайта, почему так — разберем попозже).

Давайте теперь выведем не страницу сайта, а ее исходный код. Запишем его в переменную $str и выведем на экран с помощью var_dump:

Учтите, что var_dump должен быть настроен корректно в конфигурации PHP (см. предыдущий урок для этого). Корректно — это значит вы должны видеть теги и не должно быть ограничения на длину строки (код страницы сайта может быть очень большим и желательно видеть его весь).

Итак, если все сделано хорошо, и вы видите исходный код страницы сайта — самое время приступить к его парсингу с помощью регулярных выражений.

Если вы не знаете регулярных выражений или сомневаетесь в своих знаниях — самое время изучить учебник по регулярным выражениям, а затем вернутся к изучению данного руководства по парсингу.

Должна быть включена директива allow_url_fopen http://php.net/manual/ru/filesystem.configuration.php#ini.allow-url-fopen

Парсинг с помощью регулярных выражений

При попытке разобрать HTML код с помощью регулярных выражений вас будут ждать некоторые подводные камни. Их наличие чаще всего связано с тем, что регулярные выражения не предназначены для разбора тегов — для этого есть более продвинутые инструменты, например библиотека phpQuery, которую мы будем разбирать в следующих уроках.

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

Подводные камни

Первая неожиданность, которая ожидает вас при использовании preg_match и preg_match_all — это то, что они работают только для тегов, целиком расположенных на одной строке (то есть, в них нету нажатого энтера). Если попытаться спарсить многострочный тег — у вас ничего не получится, пока вы не включите однострочный режим с помощью модификатора s. Вот таким образом:

Вторая неожиданность ждет вас, когда вы попробуете поработать с кириллицей — в этом случае нужно не забыть написать модификатор u (u маленькое, не путать с большим), вот так:

Таким образом я рекомендую вам всегда работать с этими двумя модификаторами, вот так:

Какие еще подводные камни вас ждут — будем разбирать постепенно в течении данного урока.

Попробуем разобрать теги

Пусть мы каким-то образом (например, через file_get_contents) получили HTML код сайта. Вот он:

Давайте займемся его разбором. Для начала давайте получим содержимое тега , тега , и тега .

Итак, получим содержимое тега (в переменной $str хранится HTML код, который мы разбираем):

В общем-то ничего сложного нет, только обратите внимание на то, что как уголки тегов, так и слеш от закрывающего тега экранировать не надо (последнее верно, если ограничителем регулярки является не слеш /, а, например, решетка #, как у нас сейчас).

Однако, на самом деле наши регулярки не идеальны. При некоторых условиях они просто откажутся работать. Вы должны быть готовы к этому — сайты, которые вы будете парсить — разные (часто они еще и устаревшие), и то, что хорошо работает на одном сайте, вполне может перестать работать на другом.

Что же у нас не так? На самом деле тег — такой же тег, как и остальные и в нем вполне могут быть атрибуты. Чаще всего это атрибут class, но могут быть и другие (например, onload для выполнения JavaScript).

Итак, перепишем регулярку с учетом атрибутов:

Но и здесь мы ошиблись, при чем ошибок несколько. Первая — следует ставить не плюс +, а звездочку *, так как плюс предполагает наличия хотя бы одного символа — но ведь атрибутов в теге может и не быть — и в этом случае между названием тега body и уголком не будет никаких символов — и наша регулярка спасует (не понятно, что я тут написал — учите регулярки).

Поправим эту проблему и вернемся к дальнейшему обсуждению:

Вторая проблема следующая: если внутри будут другие теги (а так оно и будет в реальной жизни) — то наша регулярка зацепит лишнего. Например, рассмотрим такой код:

Регулярка найдет не , как ожидалось, а

> — потому что мы не ограничили ей жадность. Сделаем это: место напишем — в этом случае будет все хорошо.

Но более хорошим вариантом будет написать вместо точки конструкцию [^>] (не закрывающий уголок), вот так — ]*?> — в этом случае мы полностью застрахуем себя от проблем такого рода, так как регулярка никогда не сможет выйти за тег.

Получение блока по id

Давайте рассмотрим следующий код:

Напишем регулярку, которая получит содержимое блока с id, равным content.

Итак, попытка номер один (не совсем корректная):

Что здесь не так? Проблема с пробелами — ведь между названием тега и атрибутом может быть сколько угодно пробелов, так же, как и вокруг равно в атрибутах.

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

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

Давайте поправим нашу регулярку:

Обратите внимание на то, что вокруг равно пробелы могут быть, а могут и не быть, поэтому там стоит оператор повторения звездочка *.

Кроме того, перед закрывающем уголком тега тоже могут быть пробелы (а могут и не быть) — учтем и это:

Итак, уже лучше, но еще далеко не идеал — ведь вокруг атрибута >. В этом случае наша регулярка спасует. Давайте укажем, что могут быть еще и другие атрибуты:

Обратите внимание, что после

Регулярка стала еще более хорошей, но есть проблема: лучше не использовать точку в блоках типа .*? — мы вполне можем хватануть лишнего выйдя за наш тег (помните пример выше с body?). Лучше все-таки использовать [^>] — это гарантия безопасности:

Следующая проблема: кавычки-то в атрибутах могут быть как одинарными, так и двойными (их даже может вообще не быть, если значение атрибута — одно слово, но этот случай редкий — не будем его учитывать, если вам встретится такой сайт — проще написать регулярку специально для него). Итак, учтем это:

Обратите внимание на то, что одинарная кавычка заэкранирована — мы это делаем, так как внешние кавычки от строки PHP у нас тоже одинарные, вот тут:

В общем-то регулярка достаточно хороша, но иногда идут дальше и делают так, чтобы первая кавычка от тега совпадала со второй (исключаем вариант >

Для нашей задачи это особо не нужно (можно быть точно уверенным, что такое > — в атрибуте title вполне может затесаться одинарная кавычка и регулярка title\s*?=\s*?[«\’](.+?)[«\’] вытянет текст «Рассказ о д» — потому что поиск ведется до первой кавычки.

А вот регулярка title\s*?=\s*?([«\’])(.+?)\1 будет корректно обрабатывать

Проблема вложенных блоков

В нашей регулярке есть еще одна проблема — она не может работать с вложенными блоками. Например, если внутри дива #content есть еще один див — регулярка найдет текст до первого закрывающего

Наша регулярка вытянет только

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

Ну, а что делать — нужно просто привязываться не к

В HTML5 появились новые теги — header, footer, main (для контента) — с ними работать гораздо удобнее, ведь в них исключена вложенность. И очень часто вместо

Вытягиваем заданные блоки

Получение href ссылок

Ссылки из блока

Получение элементов по классу

Кодировка документа

Иногда вам придется парсить не современные сайты, а достаточные старые. На таких сайтах кодировка чаще всего установлена в windows-1251. Поэтому, если вы попытаетесь получить русскоязычные тесты с этого сайта, вы вместо русских букв увидите вопросики — это первый признак сбившейся кодировки.

В этом случае следует воспользоваться функцией iconv, которая перекодирует текст из устаревшего windows-1251 в современный utf-8:

Как понять по HTML коду сайта, что в нем не та кодировка? Посмотрите на тег meta charset. Он может выглядеть так или так . Во втором случае кодировка не та.

Кстати, в HTML5 кодировка устанавливается так , а варианты кодировки с http-equiv=»content-type» устарели. Однако, на сайтах сейчас можно встретить и тот, и другой вариант.

Кстати, на сайте может вообще не быть тега meta charset — в этом случае кодировка файла windows-1251 (в подавляющем большинстве случаев).

Что вам делать дальше:

Приступайте к решению задач по следующей ссылке: задачи к уроку.

Когда все решите — переходите к изучению новой темы.

Замена внешних ссылок на внутренние или как спрятать ссылку (Часть 2)

Здравствуйте, в первой части урока мы создали файл exit.php в котором сделали редирект, но чтобы каждый раз в ручную не подставлять к ссылке «exit.php?url=» мы создадим регулярное выражение с помощью которого автоматически найдем все внешние ссылки и заменим их на внутренние.

Итак часть 2 — «Регулярные выражения»

Для начала надо определиться, что будем искать с помощью регулярки. А искать будем все активные ссылки начинающиеся на HTTP:// , HTTPS:// или FTP:// . Полезные функции на PHP — активная ссылка, по которой можно кликнуть. Теперь давайте разберем из чего состоит html код такой ссылки.

Теперь мы знаем что искать.

Собираем регулярку

Разберем по порядку (

  1. () — все что находится в круглых скобках — это группа
  2. [] — квадратные скобки говорят о диапазоне, т.е. [abc] — будет означать либо а , либо b либо с
  3. [a-z_»\-\s\=]* — строка может содержать символы в диапазоне от a до z , _ , кавычки, тире, знак равно и \s — пробел. А * звездочка после квадратных скобок говорит о том, что данные символы могут встретиться ноль и более раз.

Затем ищем href=»

А после нужно указать, что протокол может быть: либо HTTP либо HTTPS либо FTP.

Здесь тоже все просто, указываем в скобках (https | ftp). символ | — означает «либо», тоесть либо https либо ftp . А после буквы s (http S ) ставим знак вопроса — это скажет о том, что буква S может быть 1 раз, или её может совсем не быть. А после протокола ставим ://

Регулярное выражение для поиска активных ссылок.

Буква i в конце регулярки говорит о том, что поиск будет регистронезависимым, т.е. строка » АбВгД » ничем не будет отличаться от » абвгд «.

Как использовать данный код:

Использовать мы его будем с функцией preg_replace().

У данной функции есть три параметра:

  1. Регулярное выражение
  2. На что меняем
  3. То что меняем

Рассмотрим пример:

Объясняю что означает $1,$2 и $3 — это группы, для обозначения групп в регулярке, мы использовали круглые скобочки.

Пример регулярных выражений: поиск ссылок HREF Regular Expression Example: Scanning for HREFs

В следующем примере показаны поиск и вывод всех значений href=». «, а также их позиций в строке. The following example searches an input string and displays all the href=»…» values and their locations in the string.

Объект Regex The Regex Object

Поскольку метод DumpHRefs может быть вызван из пользовательского кода несколько раз, он использует метод static ( Shared в Visual Basic) Regex.Match(String, String, RegexOptions). Because the DumpHRefs method can be called multiple times from user code, it uses the static ( Shared in Visual Basic) Regex.Match(String, String, RegexOptions) method. Это позволяет обработчику регулярных выражений кэшировать регулярное выражение и избежать дополнительной нагрузки, связанной с созданием объекта Regex при каждом вызове метода. This enables the regular expression engine to cache the regular expression and avoids the overhead of instantiating a new Regex object each time the method is called. Затем объект Match выполняет итерацию по всем совпадениям в строке. A Match object is then used to iterate through all matches in the string.

В следующем примере показан вызов метода DumpHRefs . The following example then illustrates a call to the DumpHRefs method.

Возможные интерпретации шаблона регулярного выражения href\s*=\s*(?:[«‘](? [^»‘]*)[«‘]|(? \S+)) показаны в следующей таблице. The regular expression pattern href\s*=\s*(?:[«‘](? [^»‘]*)[«‘]|(? \S+)) is interpreted as shown in the following table.

Шаблон Pattern ОПИСАНИЕ Description
href Совпадение с литеральной строкой «href». Match the literal string «href». Сопоставление не учитывает регистр. The match is case-insensitive.
\s* Соответствует нулю или нескольким символам пробела. Match zero or more white-space characters.
= Соответствует знаку равенства. Match the equals sign.
\s* Соответствует нулю или нескольким символам пробела. Match zero or more white-space characters.
(?:\[«‘\](? \[^»‘\]*)[«‘]|(? \S+)) Соответствует одному из следующих символов, не назначая результат группе записи. Match one of the following without assigning the result to a captured group:

Кавычки или апостроф, за которыми следует ноль или несколько любых символов, кроме кавычек или апострофа, за которыми следуют кавычки или апостроф. A quotation mark or apostrophe, followed by zero or more occurrences of any character other than a quotation mark or apostrophe, followed by a quotation mark or apostrophe. В этот шаблон включена группа с именем 1 . The group named 1 is included in this pattern.

Один или более символов, которые не являются пробелами. One or more non-white-space characters. В этот шаблон включена группа с именем 1 . The group named 1 is included in this pattern.

(? [^»‘]*) Присвоить ноль или несколько любых символов, кроме кавычки или апострофа, группе записи 1 . Assign zero or more occurrences of any character other than a quotation mark or apostrophe to the capturing group named 1 .
(? \S+) Присвоить один или несколько символов, отличных от пробела, захваченной группе с именем 1 . Assign one or more non-white-space characters to the capturing group named 1 .

Класс результата поиска Match Result Class

Результаты поиска сохраняются в классе Match, который предоставляет доступ ко всем подстрокам, извлеченным в ходе поиска. The results of a search are stored in the Match class, which provides access to all the substrings extracted by the search. Также он запоминает искомую строку и использованное регулярное выражение, что позволяет вызвать метод Match.NextMatch для продолжения поиска с того места, где закончился предыдущий. It also remembers the string being searched and the regular expression being used, so it can call the Match.NextMatch method to perform another search starting where the last one ended.

Явно именованные шаблоны Explicitly Named Captures

В обычных регулярных выражениях круглые скобки, обозначающие отдельные шаблоны, автоматически последовательно нумеруются. In traditional regular expressions, capturing parentheses are automatically numbered sequentially. В связи с этим возникают две проблемы. This leads to two problems. Во-первых, если регулярное выражение изменяется из-за вставки или удаления пары круглых скобок, все части кода, которые ссылаются на нумерованные шаблоны, необходимо переписать, чтобы отразить новую нумерацию. First, if a regular expression is modified by inserting or removing a set of parentheses, all code that refers to the numbered captures must be rewritten to reflect the new numbering. Во-вторых, вследствие того, что различные пары круглых скобок часто используются для определения двух альтернативных выражений для поиска, трудно определить, какое из двух выражений в действительности вернуло результат. Second, because different sets of parentheses often are used to provide two alternative expressions for an acceptable match, it might be difficult to determine which of the two expressions actually returned a result.

Регулярные выражения в PHP

Регулярные выражения ( сокращенно — regex ) представляют собой последовательности символов, которые формируют шаблоны поиска. В основном они используются в шаблонах сопоставления со строками.

  • Все началось в 1940 — 1960-х годах, когда множество умных людей говорили о регулярных выражениях;
  • 1970-е годы g / re / p;
  • 1980 Perl и Генри Спенсер;
  • 1997 PCRE (регулярные выражения, совместимые с Perl). Именно тогда начался взлет того, что мы называем регулярные выражения. PCRE предоставляет библиотеки почти для каждого языка.

Общее использование регулярных выражений в PHP

PHP включает в себя три основные функции для работы с PCRE — preg_match , preg_match_all и preg_replace .

Выражение возвращает 1 , если соответствие установлено, 0 — если нет, и false — если возникает ошибка:

Регулярного выражения пример, который возвращает количество найденных совпадений:

Выражение возвращает замененную строку или массив ( на основе объекта $subject ):

Общее использование регулярных выражений в JavaScript

Регулярные выражения в JavaScript выглядят почти так же, как и в PHP .

Возвращает массив совпадений или null , если совпадений не найдено:

Регулярное выражение, которое возвращает строку с выполненными заменами:

Особенности регулярных выражений в JavaScript

  • Точка никогда не соответствует новой строке:
  • Те же методы для сравнения соответствия и замены через регулярное выражение, что и без них.

Принципы составления шаблонов регулярных выражений

Рассмотрим пример, в котором нужно найти адреса электронной почты в базе кода. Наша цель: /[w.+-][email protected][a-z0-9-]+(.[a-z0-9-]+)*/i

Регулярные выражения состоят из двух типов символов:

  • специальные символы: []? * + <> () ^ $ / .
  • Литералы.

Представьте себе входные строки как болты, а шаблон — как набор разъемов для них (в соответствующем порядке).

При проверке регулярных выражений нужно знать, как работают специальные символы:

  • Символ обратной косой черты \ может заменять другой специальный символ в регулярном выражении:
  • Точка и w — .

Совпадение со всеми символами, кроме новых строк. Если хотите проверить на соответствие точке, и только точке — , на соответствие буквам, цифрам и нижнему подчеркиванию — w

Совпадение с символами внутри скобок. Поддерживает диапазоны. Некоторые примеры:
o [abc] — соответствует любым a, b или c.
o [a-z] прописные буквы.
o [0-9] любая цифра.
o [a-zA-Z] — соответствует любому буквенному символу в нижнем или верхнем регистре.
• Опционально ? Соответствие 0 или 1.
• Звездочка *.

Звездочка обозначает 0 или более символов.

Соответствие 1 или более символам.

Минимальное и максимальное значения. Некоторые примеры синтаксиса регулярных выражений:
o <1,>не менее 1.
o <1,3>от 1 до 3.
o <1,64>от 1 до 64.

Добавим все это, чтобы получить регулярное выражение для адресов электронной почты:

Как это выглядит в PHP :

Использование регулярного выражения для валидации

Задача : убедиться, что вводимые данные — это то, что мы ожидаем. Цель 1 : /[^[]w$.]/ Цель 2: /^[0-9]<1,2>[dwmy]$/

Регулярные выражения подходят для поиска элементов, но вам нужно знать, что именно вы ищете.

Когда не стоит использовать регулярное выражение для проверки?

Многие случаи лучше обрабатывать с помощью функции PHP filter_var . Например, проверка адреса электронной почты должна выполняться с помощью встроенных фильтров PHP :

Валидация с помощью регулярных выражений

Регулярные выражения в конце строки используют анкоры:

^ — указывает начало строки.
$ — знак доллара, который указывает конец строки.

Исключенные классы символов

[^abc] — все, кроме a , b или c , включая новые строки.

Пример, который обеспечивает ввод только буквенно-цифровых символов, тире, точки, подчеркивания:

Поиск и замена

Наиболее распространенными функциями PCRE для выполнения поиска и замены являются preg_replace() и preg_replace_callback() . Но есть также preg_filter() и preg_replace_callback_array() , которые делают почти то же самое. Обратите внимание, что функция preg_replace_callback_array() доступна, начиная с PHP7 .

Заменить слова в списке

Если в регулярном выражении есть подшаблоны ( в круглых скобках ), можно заменить $N или N ( где N является целым числом > = 1 ), это называется «обратная ссылка».

Перестановка двух чисел

Изменение форматирования даты

Простой пример замены URL-адреса в теге

Иногда нужно выполнить сложный поиск и замену, например, при фильтрации/проверке перед заменой. В этой ситуации может пригодиться preg_replace_callback() .

Приведенное в предыдущем примере регулярное выражение может заменить только URL-адреса , начинающиеся с http или https . Но теперь нам также нужно заменить URL-адреса, начинающиеся с www. Кто-то подумает, что можно просто изменить https? : // в подшаблоне. Например, на ( ?: Https? : // | www . ), Но это не будет работать в большинстве браузеров, потому что они будут интерпретировать www.domain как относительный путь.

Поэтому в конструкторе регулярных выражений перед заменой нужно выполнить некоторые действия, добавив http:// , если URL-адрес начинается с www .

Проблема : ссылка @mentions и #tags
Цель : /[email protected]([w]<2,>)/i

Данная публикация представляет собой перевод статьи « Regex — regular expressions in PHP » , подготовленной дружной командой проекта Интернет-технологии.ру

Регулярное выражение PHP для поиска всех ссылок

iko, абсолютно тупая функция

bearman добавил 01.06.2010 в 20:58
еще и работающая коряво в некоторых случаях

***93;*>(.*) /iU», $content, $links); // Собираем ссылки

if (sizeof($links***91;1***93;) > 0) // Если ссылки найдены
<
$out = array(); // Массив для внешних ссылок

foreach ($links***91;1***93; as $v)
<
if (preg_match(«/http:\/\/(www\.)<0,1>«.$domain.»/i», $v)) // Пропускаем внутренние ссылки
<
continue;
>

01.06.2010, 21:56 #6
01.06.2010, 22:22 #7
01.06.2010, 22:27 #8

[html]
$content = preg_replace(«/[\n\r\t]/», », $content); // Заменяем символы перевода строки и табуляции на пробел
$content = preg_replace(«/[ ]<2,>/», ‘ ‘, $content); // Заменяем более 2х пробелов одним
[/html]

[html]
$content = preg_replace(«/\s+/», ‘ ‘, $content);
[/html]ну и дальше больше всяких вещей можно)

HackWare.ru

Этичный хакинг и тестирование на проникновение, информационная безопасность

Регулярные выражения в PHP (ч. 2)

Оглавление

Первая часть:

Вторая часть:

Рекомендуется начать знакомство с регулярными выражениями в PHP с первой части.

Общие типы символов

Теперь мы опять вернёмся к синтаксису, который может использоваться при написании регулярных выражений. В отличие от ранее рассмотренных основ, описанное ниже является более сложным и применяется реже, либо может быть описано с помощью уже рассмотренного синтаксиса.

Например, далее рассмотрены способы указания общего типа символов — некоторые из этих способов записи являются альтернативным синтаксисом к уже рассмотренным. Допустим если мы хотим указать в регулярном выражении «любая цифра», то мы можем использовать [0-9]. Также имеется ещё один вариант записи с помощью экранирующих последовательностей. «Любая десятичная цифра» в них обозначается как \d.

Экранирующие последовательности — это набор символов, которые начинаются с обратного слэша \ и, следовательно, которые теряют своё буквальное значение, а начинают иметь специальное значение. Получается, что для специальных символов обратный слэш отключает их специальное значение, а для обычных букв и цифр он включает специальное значение (если оно предусмотрено).

Среди экранирующих последовательностей есть элементы синтаксиса, который невозможно передать иным способом. Примеры будут показаны далее.

Общие типы символов обозначаются так:

\d

любая десятичная цифра

\D

любой символ, кроме десятичной цифры

\h

любой горизонтальный пробельный символ

\H

любой символ, не являющийся горизонтальным пробельным символом

\s

любой пробельный символ

\S

любой непробельный символ

\v

любой вертикальный пробельный символ

\V

любой символ, не являющийся вертикальным пробельным символом

\w

Любой символ, образующий «слово»

\W

Любой символ, не образующий «слово»

Каждая пара таких специальных последовательностей делит полное множество всех символов на два непересекающихся множества. Любой символ соответствует одному и только одному множеству из пары.

Следующие символы считаются как «пробельные»: HT (9), LF (10), FF (12), CR (13), и пробел (32). Тем не менее, если идет локале-зависимый поиск, и произойдет совпадение с символами в диапазоне 128-255, они также будут восприняты как пробельные, например NBSP (A0).

Символ, образующий «слово» — это произвольная цифра, буква или символ подчеркивания, проще говоря, любой символ, который может являться частью «слова» в Perl. Определение букв и цифр управляется символьными таблицами, с которыми была собрана PCRE. И, как следствие, эти наборы могут отличаться в различных локализированных дистрибутивах. Например, в локали «fr» (Франция) некоторые символы с кодом выше 128 используются для записи ударных символов и, соответственно, соответствуют маске \w.

Описанные выше типы символов могут применяться как внутри, так и вне символьных классов, и соответствуют одному символу данного типа. Если текущая точка сравнения находится в конце строки, ни один из них не сможет совпасть, так как нет символа, с которым могло бы произойти совпадение.

У этих символов может быть весьма полезное применение. Давайте вспомним (чуть переделанное) регулярное выражение для вывода HTML тэга всех заголовков вместе с конечным тегом, а также вместе с самим содержанием заголовка:

Используя уже известный код:

я получил вот такой результат:

Найдено всего 15 совпадений, хотя мы помним, что на этой странице заголовков намного больше. Дело в том, что найдены только заголовки, которые в HTML коде записаны в одну строку, например так:

А если запись разбита на несколько строк, например так:

то такие заголовки найдены не были.

Проблема не в каких-то ограничениях регулярных выражений — в PHP анализ текста происходит именно целиком, то есть даже если текст состоит из нескольких строк, в PHP он анализируется за раз, без разбития на строки.

Проблема в нашем регулярном выражении, которое мы написали — мы не указали, что после открывающего тэга заголовка могут идти пробелы. Затем после содержимого заголовка также могут идти пробелы. Давайте составим новое регулярное выражение, с учётом этого. Любые пробельные символы обозначаются как \s. Их может не быть вовсе, а может быть несколько, поэтому в качестве квантора нужно использовать звёздочку, получаем \s*. Эту конструкцию вставляем два раза: 1) между открывающим HTML тэгом и содержимым заголовка; 2) между концом содержимого заголовка и закрывающим HTML тэгом.

Получаем такое регулярное выражение:

В результате находим 51 заголовок — видимо, это все заголовки анализируемой страницы, среди них как написанный в одну строку, так и многострочные.

В подобных случаях также можно использовать модификатор регулярного выражения s. Подробности и примеры смотрие в статье «Поиск по нескольким строкам в PHP с функциями preg_match_all и preg_match».

Следующие два раздела (непечатные символы и определение формальных утверждений) — нечасто применимы, поэтому если вы в них не разобрались, то просто переходите к последующим параграфам.

Непечатные символы в видимой форме в описании шаблона

В PCRE нет ограничений на использование непечатных символов (исключая бинарный ноль, который интерпретируется как конец шаблона), тем не менее, при редактировании программного кода в каком-либо текстовом редакторе гораздо удобнее использовать следующие комбинации, чем реальные символы, которые они представляют:

\a

символ оповещения, сигнал, (BEL, шестнадцатеричный код 07)

\cx

«Ctrl+x«, где x — произвольный символ

\e

escape (шестнадцатеричный код 1B)

\f

разрыв страницы (шестнадцатеричный код 0C)

\n

перевод строки (шестнадцатеричный код 0A)

символ со свойством xx, подробнее смотрите свойства unicode

символ без свойства xx, подробнее смотрите свойства unicode

\r

возврат каретки (шестнадцатеричный код 0D)

\R

разрыв строки: совпадает с \n, \r и \r\n

\t

табуляция (шестнадцатеричный код 09)

\xhh

символ с шестнадцатеричным кодом hh

\ddd

символ с восьмеричным кодом ddd, либо ссылка на подмаску

Если быть более точным, комбинация «\cx» интерпретируется следующим образом: если «x» — символ нижнего регистра, он преобразуется в верхний регистр. После этого шестой бит символа (шестнадцатеричный код 40) инвертируется. Таким образом «\cz» интерпретируется как шестнадцатеричное значение 1A, в то время как «\c<" получает шестнадцатеричное значение 3B, а "\c;" - 7B.

После «\x» считываются еще две шестнадцатеричные цифры (они могут быть записаны в нижнем или верхнем регистре). В режиме UTF-8, разрешается использование «\x<. >«, где содержимое скобок является строкой из шестнадцатеричных цифр. Она интерпретируется как символ UTF-8 character с кодом, совпадающим с данным шестнадцатеричным числом. Исходная шестнадцатеричная экранирующая последовательность, \xhh, совпадает с двухбайтным UTF-8 символом, если его значение превышает 127.

После «\0» считываются две восьмеричные цифры. Если в записи менее двух цифр, будут использованы все фактически присутствующие цифры. Таким образом, последовательность «\0\x\07» будет интерпретирована как два бинарных нуля, за которыми следует символ оповещения (звонок). В случае, если вы используете представление числа в восьмеричном коде, убедитесь, что за начальным нулем следуют две значащие цифры.

Обработка обратного слеша, за которым следует ненулевая цифра, несколько сложнее. Вне символьного класса PCRE воспринимает обратный слеш и следующие за ним цифры как десятичное число. Если полученное значение меньше десяти, либо если шаблон содержит по меньшей мере такое же количество предшествующих текущей позиции подмасок, вся конструкция интерпретируется как ссылка на подмаску. Более детальное описание будет приведено ниже при обсуждении механизма работы подмасок.

Внутри символьного класса, либо если полученное значение больше 9 и соответствующее количество предшествующих подмасок отсутствует, PCRE считывает до трех восьмеричных цифр, следующих за обратным слешем, и генерирует один байт из последних 8-ми значащих битов полученного значения. Все последующие цифры обозначают себя же. Например:

\040

еще один способ записи пробела

\40

то же самое в случае, если данной записи предшествует менее сорока подмасок

\7

всегда интерпретируется как ссылка на подмаску

\11

может быть как обратной ссылкой, так и альтернативной записью символа табуляции

\011

всегда интерпретируется как символ табуляции

\0113

символ табуляции, за которым следует цифра «3»

\113

интерпретируется как символ с восьмеричным кодом 113 (так как ссылок на подмаски не может быть более чем 99)

\377

байт, всецело состоящий из единичных битов

\81

либо обратная ссылка, либо бинарный ноль, за которым следуют цифры «8» и «1»

Следует помнить, что восьмеричные значения, превышающие 100, следует писать без лидирующего нуля, так как читается не более трех восьмеричных цифр.

Все последовательности, определяющие однобайтное значение, могут встречаться как внутри, так и вне символьных классов. Кроме того, внутри символьного класса запись «\b» интерпретируется как символ возврата (‘backspace’, шестнадцатеричный код 08). Вне символьного класса она имеет другое значение (какое именно, описано ниже).

Определение формальных утверждений

Ещё одно использование обратного слеша — определение некоторых формальных утверждений, описывающих условия касательно месторасположения особых позиций в строке и совершенно не затрагивающих сами символы. Использование подмасок как более сложных формальных утверждений описано далее. Такими управляющими последовательностями являются:

\b

\B

не является границей слова

\A

начало данных (независимо от многострочного режима)

\Z

конец данных либо позиция перед последним переводом строки (независимо от многострочного режима)

\z

конец данных (независимо от многострочного режима)

\G

первая совпадающая позиция в строке

Описанные выше последовательности не могут встречаться в символьных классах (исключая комбинацию «\b«, которая внутри класса означает символ возврата ‘backspace’).

Границей слова считается такая позиция в строке, в которой из текущего и предыдущего символа только один соответствует \w или \W (т.е. один из них соответствует \w, а другой \W). Начало или конец строки также соответствуют границе слова в случае, если первый или, соответственно, последний символ совпадает с \w.

Специальные последовательности \A, \Z и \z отличаются от общеупотребляемых метасимволов начала строки ‘^‘ и конца строки ‘$‘ (описанных в разделе якоря первой части) тем, что они всегда совпадают либо в самом начале либо в самом конце строки. На них никак не влияют опции m (PCRE_MULTILINE) и D (PCRE_DOLLAR_ENDONLY). Разница между \Z и \z в том, что \Z соответствует позиции перед последним символом в случае, если последний символ — перевод строки, кроме самого конца строки. В то время, как \z соответствует исключительно концу данных.

Утверждение \G является истинным только в том случае, если текущая проверяемая позиция находится в начале совпадения, указанного параметром offset функции preg_match(). Она отличается от \A при ненулевом значении параметра offset.

\Q и \E могут быть использованы для игнорирования метасимволов регулярных выражений в шаблоне. Например: \w+\Q.$.\E$ совпадет с один или более символов, составляющих «слово»,за которыми следуют символы .$. и якорь в конце строки.

Последовательность \K может быть использована для сброса начала совпадения. Например, шаблон foo\Kbar совпадет с «foobar», но сообщит о том, что совпал только с «bar». Использование \K не мешает установке подмасок. Например, если шаблон (foo)\Kbar совпадет со строкой «foobar», первой подмаской все равно будет являться «foo».

POSIX нотация для символьных классов

Perl поддерживает нотацию POSIX для символьных классов. Это включает использование имен, заключенных в [: и :], в свою очередь заключенных в квадратные скобки. PCRE также поддерживает эту запись. Например, [01[:alpha:]%] совпадет с «0», «1», любым алфавитным символом или «%«. Поддерживаются следующие имена классов:

01.06.2010, 22:30 #9
alnum буквы и цифры
alpha буквы
ascii символы с кодами 0 — 127
blank только пробел или символ табуляции
cntrl управляющие символы
digit десятичные цифры (то же самое, что и \d)
graph печатные символы, исключая пробел
lower строчные буквы
print печатные символы, включая пробел
punct печатные символы, исключая буквы и цифры
space пробельные символы(почти то же самое, что и \s)
upper прописные буквы
word символы «слова» (то же самое, что и \w)
xdigit шестнадцатеричные цифры

Класс пробельных символов (space) — это горизонтальная табуляция (HT, 9), перевод строки (LF, 10), вертикальная табуляция (VT, 11), разрыв страницы (FF, 12), возврат каретки (CR, 13) и пробел (32). Учтите, что этот список включает вертикальную табуляцию (VT, код 11). Это отличает «space» от \s, который не включает этот символ (для совместимости с Perl).

Название word — это расширение Perl, а blank — расширение GNU, начиная с версии Perl 5.8. Другое расширение Perl — это отрицание, которое указывается символом ^ после двоеточия. Например, [12[:^digit:]] совпадет с «1», «2», или с любой не-цифрой.

В режиме UTF-8, символы со значениями, превышающими 128, не совпадут ни с одним из символьных классов POSIX. Начиная с PHP 5.3.0 и libpcre 8.10 некоторые символьные классы изменены, чтобы использовать свойства символов Unicode, в этом случае упомянутое ограничение не применяется. Читайте руководство PCRE(3) для подробностей.

Подмаски

Подмаска — это часть регулярного выражения, которая участвует в поиске. Подмаска может выполнять несколько функций:

1) если была найдена строка, соответствующая целому регулярному выражению, то в результаты поиска будут возвращены две строки: во-первых, соответствующая всему регулярному выражению, и, во-вторых, соответствующая подмаске

2) найденная в подмаске строка может вновь использоваться в регулярном выражении в качестве обратной ссылке (о них позже)

Подмаски в регулярном выражении выделяются скобками. В регулярном выражении может быть более чем одна подмаска, в этом случае они нумеруются слева направо.

Подмаски могут быть вложенными одна в другую.

При использовании функции preg_match_all возвращается массива, где в качестве первого элемента (с индексом 0) возвращается массив с найденными значениями строк. Если указаны подмаски, то в качестве второго элемента возвращаемого массива (с индексом 1) будет массив с найденными строками, соответствующими первой подмаске. Если используется две подмаски, то будет возвращён ещё один массив и так далее для каждой последующей подмаске.

Как мы помним из первой части, описывающий синтаксис регулярных выражений, скобки имеют и другое значение: или использовании оператора | (ИЛИ) они ограничивают варианты альтернатив друг от друга. Например, шаблон cat(aract|erpillar|) соответствует одному из слов «cat», «cataract» или «caterpillar». Без использования скобок он соответствовал бы строкам «cataract», «erpillar» или пустой строке.

То есть скобки выполняют одновременно две функции.

На самом деле выполнение одновременно двух функций не всегда удобно. Бывают случаи, когда необходима группировка альтернатив без захвата строки. В случае, если после открывающей круглой скобки следует «?:«, захват строки не происходит, и текущая подмаска не нумеруется. Например, если строка «the white queen» сопоставляется с шаблоном the ((?:red|white) (king|queen)), будут захвачены подстроки «white queen» и «queen», и они будут пронумерованы 1 и 2 соответственно. Максимальное количество захватывающих подмасок — 65535. Такие большие шаблоны могут не скомпилироваться, в зависимости от настроек libpcre.

В случае, если в незахватывающей подмаске необходимо указать дополнительные опции, можно воспользоваться удобным сокращением: символ, обозначающий устанавливаемую опцию помещается между «?» и «:«. Таким образом, следующие два шаблона

соответствуют одному и тому же набору строк. Поскольку альтернативные версии берутся слева направо, и установленные опции сохраняют своё действие до конца подмаски, опция, установленная в одной ветке, также имеет эффект во всех последующих ветках. Поэтому приведенные выше шаблоны совпадают как с «SUNDAY», так и с «Saturday».

Также можно использовать именованные подмаски с помощью синтаксиса (?P pattern). Эта подмаска будет индексирована в массиве совпадений кроме обычного числового индекса, еще и по имени name. В PHP 5.2.2 было добавлено два альтернативных синтаксиса: (? pattern) и (?’name’pattern).

Иногда бывает необходимо иметь несколько совпадений, исключающих друг друга. Обычно, каждое такое совпадение получает свой собственный номер, даже если шаблон позволяет совпасть только одному из них. Синтаксис (?| позволяет обойти это поведение и убрать дублирующиеся номера. Рассмотрим следующее регулярное выражение, сопоставленное со строкой Sunday:

Здесь Sun сохраняется в ссылке 2, тогда как ссылка 1 пуста. Если же совпадет Sat, то она будет помещена в ссылку 1, а ссылка 2 вообще не будет существовать. Использование (?| в шаблоне решает эту проблему:

В этом шаблоне обе подмаски Sun и Sat будут сохранены под номером 1.

Обратные ссылки в PHP

Как мы только что выяснили, строки, найденные в подмасках, возвращаются вместе с основными найденными строками. Но их можно использовать в самих регулярных выражениях.

Вне символьного класса обратный слеш с последующей цифрой больше нуля (и, возможно, последующими цифрами) интерпретируется как ссылка на предшествующую захватывающую подмаску, предполагая, что соответствующее количество предшествующих открывающих круглых скобок присутствует.

Однако, в случае, если следующее за обратным слешем число меньше 10, оно всегда интерпретируется как обратная ссылка, и приводит к ошибке только в том случае, если нет соответствующего числа открывающих скобок. Другими словами, открывающие скобки не обязаны предшествовать ссылке для чисел меньше 10. «Упреждающая обратная ссылка» может иметь смысл, если используется повторение и более поздняя подмаска участвует в ранней итерации. Более детальную информацию об обработке цифр после обратного слеша можно найти в разделе «Обратный слеш».

Обратная ссылка сопоставляется с частью строки, захваченной соответствующей подмаской, но не с самой подмаской. Таким образом шаблон (sens|respons)e and \1ibility соответствует «sense and sensibility», «response and responsibility», но не «sense and responsibility». В случае, если обратная ссылка обнаружена во время регистрозависимого поиска, то при сопоставлении обратной ссылки регистр также учитывается. Например, ((?i)rah)\s+\1 соответствует «rah rah» и «RAH RAH», но не «RAH rah», хотя сама подмаска сопоставляется без учета регистра.

На одну и ту же подмаску может быть несколько ссылок. Если подмаска не участвовала в сопоставлении, то сопоставление со ссылкой на нее всегда терпит неудачу. Например, шаблон (a|(bc))\2 терпит неудачу, если находит соответствие с «a» раньше, чем с «bc». Поскольку может быть до 99 обратных ссылок, все цифры, следующие за обратным слешем, рассматриваются как часть потенциальной обратной ссылки. Если за ссылкой должна следовать цифра, необходимо использовать ограничитель. В случае, если указан флаг x (PCRE_EXTENDED), ограничителем может быть любой пробельный символ. В противном случае можно использовать пустой комментарий.

Ссылка на подмаску, внутри которой она расположена, всегда терпит неудачу, если это первое сопоставление текущей подмаски. Например, шаблон (a\1) не соответствует ни одной строке. Но все же такие ссылки бывают полезны в повторяющихся подмасках. Например, шаблон (a|b\1)+ совпадает с любым количеством «a», «aba», «ababaa». При каждой итерации подмаски обратная ссылка соответствует той части строки, которая была захвачена при предыдущей итерации. Чтобы такая конструкция работала, шаблон должен быть построен так, чтобы при первой итерации сопоставление с обратной ссылкой не производилось. Этого можно достичь, используя альтернативы (как в предыдущем примере), либо квантификаторы с минимумом, равным нулю.

Начиная с PHP 5.2.2, управляющая последовательность \g может быть использована для абсолютных и относительных ссылок на подмаски. После этой последовательности должно быть указано беззнаковое или отрицательное число, при желании заключенное в фигурные скобки. Последовательности \1, \g1 и \g эквивалентны друг другу. Использование этого шаблона с беззнаковым числом поможет избежать двусмысленности, присущей числам после обратного слеша. Это также помогает отличить обратные ссылки от символов в восьмеричном формате, а также упрощает запись числового литерала сразу после обратной ссылки, например, \g<2>1.

Использование отрицательных чисел с \g полезно при использовании относительных ссылок. Например, (foo)(bar)\g соответствует «foobarbar», а (foo)(bar)\g соответствует «foobarfoo». Это также может быть полезно в длинных шаблонах, в качестве альтернативы отслеживания числа подмасок, на которые можно ссылаться в последующей части шаблона.

Указать обратную ссылку на именованную подмаску можно с помощью (?P=name) или, начиная с PHP 5.2.2, \k или \k’name‘. Кроме того, в PHP 5.2.4 была добавлена поддержка \k> и \g>, а в PHP 5.2.7 для \g и \g’name’.

К примеру, я хочу найти строки, состоящие из пяти любых, но одинаковых цифр, например, «11111», «22222» и так далее, в этом случае я могу написать следующее регулярное выражение:

Как мы рассмотрели чуть выше, экранирующая последовательность \d обозначает любую цифру. Для того, чтобы найденную строку можно было использовать в качестве обратной ссылке, мы заключаем эту часть регулярного выражения в круглые скобки. То есть получается, что мы создаём подмаску в регулярном выражении. Затем идёт обратный слэш \ с цифрой 1 — это и есть обратная ссылка. То есть, что бы ни было найдено в первой подмаске, его значение будет помещено в обратную ссылку \1. Затем ещё идут три таких же обратных ссылки. Получается что регулярное выражение ищет любую цифру, за которой ещё четыре раза идёт эта же самая цифра.

Для поиска возьмём строку:

даст следующий результат:

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

Рассмотрим более практический пример. Допустим мы хотим найти в HTML коде все пары тэгов: открывающий и закрывающий тэг, между которыми идёт какой-либо текст. Есть исключения (например,
, и так далее) — но не будем их рассматривать, чтобы не усложнять пример.

Тэг абзаца выглядит примерно так:

Тэг раздела страницы:

Как мы видим, в угловые скобки помещено название тэга, которое представляет собой одну или более маленьких букв. Закрывающим тэгом является эта же самая конструкция, с этим же самым названием тэга, но перед названием добавляется слэш /.

Любая буква в угловых скобках обозначается так:

Чтобы создать обратную ссылку, поместим ту часть выражения, которая обозначает буквы, в круглые скобки:

Закрывающим тэгом будет обратная ссылка, содержащая найденное название тэга, помещённая между , то есть:

Поскольку в качестве разделителя используется слэш, то тот слэш, который означает «буквальный слэш» нужно экранировать, чтобы он потерял своё специальное значение и стал трактоваться как буквальный символ, получаем:

Составленное регулярное выражение будет соответствовать тэгам в следующем написании:

Но нужно помнить, что между тэгами почти всегда есть какой-то текст. В качестве этого тэга может быть что угодно, кроме символа , поскольку этот символ означает завершение открывающего тэга, поэтому значение «пусто, либо пробел а затем любые символы кроме > любое количество раз» на языке регулярных выражений записывается так:

Помещаем эту конструкцию в ранее составленное регулярное выражение в то место, где могут быть атрибуты:

Функции PHP для поиска и замены по регулярному выражению

Рассмотренные ранее функции ищут строки по регулярному выражению (preg_match_all), либо проверяют, строку на соответствие регулярному выражению (preg_match). В случае, если нужно не просто найти строку, но и заменить её, используются следующие функции:

  • preg_filter — Производит поиск и замену по регулярному выражению
  • preg_replace_callback_array — Выполняет поиск и замену по регулярному выражению с использованием функций обратного вызова
  • preg_replace_callback — Выполняет поиск по регулярному выражению и замену с использованием callback-функции
  • preg_replace — Выполняет поиск и замену по регулярному выражению

В результате работы функции preg_replace, если найдены совпадения, возвращается новая версия subject, иначе subject возвращается нетронутым. Функция preg_filter() идентична функции preg_replace() за исключением того, что возвращает только те значения (возможно, преобразованные), в которых найдено совпадение. Подробнее о работе функций читайте по приведённым выше ссылкам.

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

Пример использование функции preg_replace_callback:

В этом примере из монотонной строки будут выбраны имена и каждое имя будет напечатано по отдельности. Для третьего имени будет написано, что это третье имя, для каждого десятого имени будет написано, что его номер кратен 10:

Пример моего реального недавнего использования функции preg_replace_callback на практике — добавления рекламы в каждый десятый комментарий — с её помощью очень легко реализовать подобную логику.

Другие функции PHP для работы с регулярными выражениями

  • preg_last_error — Возвращает код ошибки выполнения последнего регулярного выражения PCRE
  • preg_quote — Экранирует символы в регулярных выражениях
  • preg_split — Разбивает строку по регулярному выражению

Когда не нужно использовать регулярные выражения

Не используйте функцию preg_match(), если необходимо проверить наличие подстроки в заданной строке. Используйте для этого strpos() поскольку она выполнит эту задачу гораздо быстрее.

Если вам не нужна мощь регулярных выражений, то вместо preg_split вы можете выбрать более быстрые (хоть и простые) альтернативы наподобие explode() или str_split().

Замена внешних ссылок на внутренние или как спрятать ссылку (Часть 2)

Здравствуйте, в первой части урока мы создали файл exit.php в котором сделали редирект, но чтобы каждый раз в ручную не подставлять к ссылке «exit.php?url=» мы создадим регулярное выражение с помощью которого автоматически найдем все внешние ссылки и заменим их на внутренние.

Итак часть 2 — «Регулярные выражения»

Для начала надо определиться, что будем искать с помощью регулярки. А искать будем все активные ссылки начинающиеся на HTTP:// , HTTPS:// или FTP:// . Полезные функции на PHP — активная ссылка, по которой можно кликнуть. Теперь давайте разберем из чего состоит html код такой ссылки.

Теперь мы знаем что искать.

Собираем регулярку

Разберем по порядку (

  1. () — все что находится в круглых скобках — это группа
  2. [] — квадратные скобки говорят о диапазоне, т.е. [abc] — будет означать либо а , либо b либо с
  3. [a-z_»\-\s\=]* — строка может содержать символы в диапазоне от a до z , _ , кавычки, тире, знак равно и \s — пробел. А * звездочка после квадратных скобок говорит о том, что данные символы могут встретиться ноль и более раз.

Затем ищем href=»

А после нужно указать, что протокол может быть: либо HTTP либо HTTPS либо FTP.

Здесь тоже все просто, указываем в скобках (https | ftp). символ | — означает «либо», тоесть либо https либо ftp . А после буквы s (http S ) ставим знак вопроса — это скажет о том, что буква S может быть 1 раз, или её может совсем не быть. А после протокола ставим ://

Регулярное выражение для поиска активных ссылок.

Буква i в конце регулярки говорит о том, что поиск будет регистронезависимым, т.е. строка » АбВгД » ничем не будет отличаться от » абвгд «.

Как использовать данный код:

Использовать мы его будем с функцией preg_replace().

У данной функции есть три параметра:

  1. Регулярное выражение
  2. На что меняем
  3. То что меняем

Рассмотрим пример:

Объясняю что означает $1,$2 и $3 — это группы, для обозначения групп в регулярке, мы использовали круглые скобочки.

Регулярные выражения

Регулярные выражения, это очень мощный, но в то же время сложный для понимания, инструмент обработки строк. Опишу основные моменты. Регулярное выражение это шаблон строки. По этому шаблону можно искать вхождения, производить замену, проверять на соответствие шаблону.

Правила составление шаблона (pattern)

Границы шаблона должны обозначаться определенными символами, часто используют «/«, но я предпочитаю использовать «#» потому, что от обилия прямых/обратных слешей может в глазах зарябить, а «решетки» обычно больше нигде не используются. Итак: «#ТутТелоРегулярногоВыражения#«

Внутри регулярного выражения используются скобки — это подвыражения, с которыми можно производить манипуляции, пример:

Это выражение предназначено для получения параметров в строке URL. В начале строки идет спецсимвол «^» — это означает начало строки. Далее идет «/catalog/» — тут нет спецсимволов, это просто текст, который должен содержатся в строке. Затем встретили круглые скобки, т.е. дошли до первого подвыражения. В квадратных скобках обозначаются множество символов, которые могут быть в строке в этом месте. Знак «» означает перечисление. Знак «\» экранирует специальные символы. Таким образом, в первом подвыражении у нас могут идти БОЛЬШИЕ и маленькие буквы латинского алфавита, цифры от 0 до 9, знак подчеркивания, тире и точка. Тире и точка — это спецсимволы, но здесь они экранированы, поэтому здесь это просто символы. После квадратных скобок идет знак «+» — это значит предыдущий символ (а у нас это множество символов заданное в квадратных скобках) может идти 1 или больше раз. Затем идет «/» — это просто символ, и аналогичное второе подвыражение. Затем идет «\.html«, что означает текст «.html«. А затем спец символы «.*» точка означает любой символ, а звездочка любое количество предыдущего символа. Т.е. после «.html» может идти все что угодно.

Указание количества, квантификаторы

Выше мы уже рассмотрели такие символы, указывающие количество предыдущих символов, как + и *. Приведем все возможности указания количества:

, где Х это число повторений, пример: [0-9] , это значит что здесь должно быть 5 цифр
, где X минимальное количество, Y — максимальное количество повторений. Пример [0-9] — 1 или 2 цифры. [0-9] -0, 1 или 2 цифры. [0-9] — 2 и более цифр
* любое количество символов (включая 0 символов)
+ 1 и более символов
? 1 или 0 символов

Спецсимволы

\ экранирование спецсимвола
\\ обратный слеш
| Метасимвол выбора (или или)
^ Метасимвол начала строки
$ Метасимвол конца строки
\n Символ перевода строки (шестнадцатеричный код 0x0A)
\r Символ возврата каретки (шестнадцатеричный код 0x0D)
\t Символ табуляции (шестнадцатеричный код 0x09)
. Точка. Любой символ.

Для некоторых групп символов есть специальные сокращения:

\d Цифра (0-9), вместо [0-9]
\D Не цифра (любой символ кроме символов 0-9)
\s Пустой символ (обычно пробел и символ табуляции)
\S Непустой символ (все, кроме символов, определяемых метасимволом \s)
\w «Словарный» символ (символ, который используется в словах. Обычно все буквы, все цифры и знак подчеркивания (‘_‘))
\W Все, кроме символов, определяемых метасимволом \w

«Жадность»

Рассмотрим понятие жадности регулярного выражения. Например есть строка:

«сейчас будет ссылка ссылка1, и еще ссылка2, итого 2 ссылки.«

Нужно получить ссылки, для этого составили выражение:

Вроди все верно, подвыражение подходит под:

Но оно также подходит под:

— его то мы и получим, т.к. регулярные выражения по умолчанию «жадные». Снять жадность можно с помощью модификатора «U«, вот так:

Модификаторы

После регулярного выражения могут идти модификаторы: «#ТутТелоРегулярногоВыражения#ТутМодификаторы» Виды модификаторов:

i Включает режим case-insensitive, т.е. большие и маленькие буквы в выражении не различаются.
m Указывает на то, что текст, по которому ведется поиск, должен рассматриваться как состоящий из нескольких строк. По умолчанию механизм регулярных выражений рассматривает текст как одну строку вне зависимости от того, чем она является на самом деле. Соответственно метасимволы ‘^’ и ‘$’ указывают на начало и конец всего текста. Если же этот модификатор указан, то они будут указывать соответственно на начало и конец каждой строки текста.
s По умолчанию метасимвол ‘.‘ не включает в свое определение символ перевода строки. Указание этого модификатора снимает это ограничение.
U Снимает жадность регулярного выражения
u Включает работу регулярных выражений с кириллицей в UTF-8, иначе работает не корректно.

php Функции для работы с регулярными выражениями

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

preg_match

Выполняет проверку на соответствие регулярному выражению:

preg_match_all

Выполняет глобальный поиск шаблона в строке:

Возвращает количество найденных вхождений шаблона (которое может быть и нулем) либо FALSE, если во время выполнения возникли какие-либо ошибки. В переменную $res попадет результат поиска в виде массива: [0] содержит массив полных вхождений шаблона, элемент [1] содержит массив вхождений первой подмаски, и так далее. Для удобства работы с регулярными выражениями я создал страницу, где в режиме online можно поработать с функцией preg_match_all

preg_replace

Каждое значение может быть строкой или массивом, в случае, если $subject массив — возвращается массив, иначе строка

preg_split

Разбивает строку по регулярному выражению:

Возвращает массив, состоящий из подстрок заданной строки subject, которая разбита по границам, соответствующим шаблону pattern.

Топ-пост этого месяца:  Функция tag_description

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