Урок по регулярным выражениям в PHP, для начинающих
Регулярные выражения в PHP.
Регулярные выражения позволяют найти в строке последовательности, соответствующие шаблону. Например шаблон «Вася(.*)Пупкин» позволит найти последовательность когда между словами Вася и Пупкин будет любое количество любых символов. Если надо найти шесть цифр, то пишем «[0-9]<6>» (если, например, от шести до восьми цифр, тогда «[0-9]<6,8>«). Здесь разделены такие вещи как указатель набора символов и указатель необходимого количества:
Вместо набора символов может быть использовано обозначение любого символа — точка, может быть указан конкретный набор символов (поддерживаются последовательности — упоминавшиеся «0-9»). Может быть указано «кроме данного набора символов».
Указатель количества символов в официальной документации по php называется «квантификатор». Термин удобный и не несет в себе кривотолков. Итак, квантификатор может иметь как конкретное значение — либо одно фиксированное («<6>«), либо как числовой промежуток («<6,8>«), так и абстрактное «любое число, в т.ч. 0» («*»), «любое натуральное число» — от 1 до бесконечности («+»: «document[0-9]+.txt»), «либо 0, либо 1» («?»). По умолчанию квантификатор для данного набора символов равен единице («document[0-9].txt»).
Для более гибкого поиска сочетаний эти связки «набор символов — квантификатор» можно объединять в метаструктуры.
Как всякий гибкий инструмент, регулярные выражения гибки, но не абсолютно: зона их применения ограничена. Например, если вам надо заменить в тексте одну фиксированную строку на другую, фиксированную опять же, пользуйтесь str_replace. Разработчики php слезно умоляют не пользоваться ради этого сложными функциями ereg_replace или preg_replace, ведь при их вызове происходит процесс интерпретации строки, а это серьезно потребляет ресурсы системы. К сожалению, это любимые грабли начинающих php-программистов.
Пользуйтесь функциями регулярных выражений только если вы не знаете точно, какая «там» строка. Из примеров: поисковый код , в котором из строки поиска вырезаются служебные символы и короткие слова а так же вырезаются лишние пробелы (вернее, все пробелы сжимаются: » +» заменяется на один пробел). При помощи этих функций я проверяю email пользователя, оставляющего свой отзыв. Много полезного можно сделать, но важно иметь в виду: регулярные выражения не всесильны. Например, сложную замену в большом тексте ими лучше не делать. Ведь, к примеру, комбинация «(.*)» в программном плане означает перебор всех символов текста. А если шаблон не привязан к началу или концу строки, то и сам шаблон «двигается» программой через весь текст, и получается двойной перебор, вернее перебор в квадрате. Нетрудно догадаться, что еще одна комбинация «(.*)» означает перебор в кубе, и так далее. Возведите в третью степень, скажем, 5 килобайт текста. Получается 125 000 000 000 (прописью: сто двадцать пять миллиардов операций). Конечно же, если подходить строго, там стольких операций не будет, а будет раза в четыре-восемь меньше, но важен сам порядок цифр.
Набор символов
. | точка | любой символ |
[ ] | квадратные скобки | класс символов («любое из»). Например [abcdef] |
[^ ] | негативный класс символов («любое кроме») | |
— | тире | обозначение последовательности в классе символов («[0-9]» цифры) |
\d | [0-9] | Только цифры |
\D | [^0-9] | Кроме цифр |
\w | [a-z0-9] | Буквы и цифры |
\W | [^a-z0-9] | Кроме букв и цифр |
\s | [ ] | Пробельные символы: пробел, табуляция, перевод строки |
\S | [^ ] | Кроме пробельных символов |
| | (одно|другое) | На этом месте может быть один из перечисленных вариантов, например: (Вася|Петя|Маша). Если Вы не хотите, чтобы это попало в выборку используйте (?: . ) |
Не пользуйтесь классом символов для обозначения всего лишь одного (вместо «[ ]+» вполне сойдет » +»). Не пишите в классе символов точку это ведь любой символ, тогда другие символы в классе будут просто лишними (а в негативном классе получится отрицание всех символов).
Квантификатор
Квантификатором можно указать как конкретное значение, так и пределы. Если число заданных подпадает под пределы квантификатора, фрагмент выражения считается совпавшим с разбираемой строкой. Синтаксис:
Если нужно указать только необходимый минимум, а максимума нет, просто ставим запятую и не пишем второе число: «<5,>» («минимум 5»). Для наиболее часто употребляемых квантификаторов есть специальные обозначения:
* | «звёздочка» или знак умножения |
+ | плюс |
? | вопросительный знак |
На практике такие символы используются чаще, чем фигурные скобки.
Якоря
^ | привязка к началу строки |
$ | привязка к концу строки |
Эти символы должны стоять соответственно в самом начале и в самом конце строки.
Жадность
Вопросительный знак выступает еще и как минимизатор квантификатора:
.*?
Результат работы примера:
Строка шаблона, как вы уже заметили, начинается и заканчивается слэшами. После второго идут параметры:
i | регистронезависимый поиск |
m | |
s | символ «.» (точка) совпадает и с переносом строки (по умолчанию нет) |
A | привязка к началу текста |
E | заставляет символ «$» совпадать только с концом текста. Игнорируется, если установлен парамерт m. |
U | Инвертирует «жадность» для каждого квантификатора (если же после квантификатора стоит «?», этот квантификатор перестает быть «жадным»). |
e | Строка замены интерпретитуется как PHP код. |
Функции для работы с регулярными выражениями
- preg_grep — Возвращает массив вхождений, которые соответствуют шаблону
- preg_match — Выполняет проверку на соответствие регулярному выражению. Данная функция ищет только первое совпадение!
- preg_match_all — Выполняет глобальный поиск шаблона в строке
- preg_quote — Экранирует символы в регулярных выражениях. Т.е. вставляет слэши перед всеми служебными символами (например, скобками, квадратными скобками и т.п.), чтобы те воспринимались буквально. Если у вас есть какой-либо ввод информации пользователем, и вы проверяете его с помощью регулярных выражений, то лучше перед этим заэкранировать служебные символы в пришедшей переменной
- preg_replace — Выполняет поиск и замену по регулярному выражению
- preg_replace_callback — Выполняет поиск по регулярному выражению и замену
- preg_split — Разбивает строку по регулярному выражению
preg_grep
Функция preg_grep — Возвращает массив вхождений, которые соответствуют шаблону
array preg_grep (string pattern, array input [, int flags])
preg_grep() возвращает массив, состоящий из элементов входящего массива input, которые соответствуют заданному шаблону pattern.
Параметр flags может принимать следующие значения:
PREG_GREP_INVERT
В случае, если этот флаг установлен, функция preg_grep(), возвращает те элементы массива, которые не соответствуют заданному шаблону pattern.
Результат, возвращаемый функцией preg_grep() использует те же индексы, что и массив исходных данных. Если такое поведение вам не подходит, примените array_values() к массиву, возвращаемому preg_grep() для реиндексации.
Пример кода:
preg_match
Функция preg_match — Выполняет проверку на соответствие регулярному выражению
int preg_match ( string pattern, string subject [, array matches [, int flags [, int offset]]]) Ищет в заданном тексте subject совпадения с шаблоном pattern
В случае, если дополнительный параметр matches указан, он будет заполнен результатами поиска. Элемент $matches[0] будет содержать часть строки, соответствующую вхождению всего шаблона, $matches[1] — часть строки, соответствующую первой подмаске, и так далее.
flags может принимать следующие значения:
PREG_OFFSET_CAPTURE
В случае, если этот флаг указан, для каждой найденной подстроки будет указана ее позиция в исходной строке. Необходимо помнить, что этот флаг меняет формат возвращаемых данных: каждое вхождение возвращается в виде массива, в нулевом элементе которого содержится найденная подстрока, а в первом — смещение.
Поиск осуществляется слева направо, с начала строки. Дополнительный параметр offset может быть использован для указания альтернативной начальной позиции для поиска. Аналогичного результата можно достичь, заменив subject на substr()($subject, $offset).
Функция preg_match() возвращает количество найденных соответствий. Это может быть 0 (совпадения не найдены) и 1, поскольку preg_match() прекращает свою работу после первого найденного совпадения. Если необходимо найти либо сосчитать все совпадения, следует воспользоваться функцией preg_match_all(). Функция preg_match() возвращает FALSE в случае, если во время выполнения возникли какие-либо ошибки.
Рекомендация: Не используйте функцию preg_match(), если необходимо проверить наличие подстроки в заданной строке. Используйте для этого strpos() либо strstr(), поскольку они выполнят эту задачу гораздо быстрее.
Пример кода
Пример кода
Пример кода
preg_match_all
Функция preg_match_all — Выполняет глобальный поиск шаблона в строке
int preg_match_all (string pattern, string subject, array matches [, int flags [, int offset]])
Ищет в строке subject все совпадения с шаблоном pattern и помещает результат в массив matches в порядке, определяемом комбинацией флагов flags.
После нахождения первого соответствия последующие поиски будут осуществляться не с начала строки, а от конца последнего найденного вхождения.
Дополнительный параметр flags может комбинировать следующие значения (необходимо понимать, что использование PREG_PATTERN_ORDER одновременно с PREG_SET_ORDER бессмысленно):
PREG_PATTERN_ORDER
Если этот флаг установлен, результат будет упорядочен следующим образом: элемент $matches[0] содержит массив полных вхождений шаблона, элемент $matches[1] содержит массив вхождений первой подмаски, и так далее.
Пример кода
Как мы видим, $out[0] содержит массив полных вхождений шаблона, а элемент $out[1] содержит массив подстрок, содержащихся в тегах.
PREG_SET_ORDER
Если этот флаг установлен, результат будет упорядочен следующим образом: элемент $matches[0] содержит первый набор вхождений, элемент $matches[1] содержит второй набор вхождений, и так далее.
Пример кода
В таком случае массив $matches[0] содержит первый набор вхождений, а именно: элемент $matches[0][0] содержит первое вхождение всего шаблона, элемент $matches[0][1] содержит первое вхождение первой подмаски, и так далее. Аналогично массив $matches[1] содержит второй набор вхождений, и так для каждого найденного набора.
PREG_OFFSET_CAPTURE
В случае, если этот флаг указан, для каждой найденной подстроки будет указана ее позиция в исходной строке. Необходимо помнить, что этот флаг меняет формат возвращаемых данных: каждое вхождение возвращается в виде массива, в нулевом элементе которого содержится найденная подстрока, а в первом — смещение.
В случае, если никакой флаг не используется, по умолчанию используется PREG_PATTERN_ORDER.
Поиск осуществляется слева направо, с начала строки. Дополнительный параметр offset может быть использован для указания альтернативной начальной позиции для поиска. Аналогичного результата можно достичь, заменив subject на substr()($subject, $offset).
Возвращает количество найденных вхождений шаблона (может быть нулем) либо FALSE, если во время выполнения возникли какие-либо ошибки.
Пример кода
Пример кода
preg_quote
Функция preg_quote — Экранирует символы в регулярных выражениях
string preg_quote (string str [, string delimiter])
Функция preg_quote() принимает строку str и добавляет обратный слеш перед каждым служебным символом. Это бывает полезно, если в составлении шаблона участвуют строковые переменные, значение которых в процессе работы скрипта может меняться.
В случае, если дополнительный параметр delimiter указан, он будет также экранироваться. Это удобно для экранирования ограничителя, который используется в PCRE функциях. Наиболее распространенным ограничителем является символ ‘/’.
В регулярных выражениях служебными считаются следующие символы: . \\ + * ? [ ^ ] $ ( ) < >= ! | :
Пример кода
Пример кода
preg_replace
Функция preg_replace — Выполняет поиск и замену по регулярному выражению
mixed preg_replace ( mixed pattern, mixed replacement, mixed subject [, int limit])
Выполняет поиск в строке subject совпадений с шаблоном pattern и заменяет их на replacement. В случае, если параметр limit указан, будет произведена замена limit вхождений шаблона; в случае, если limit опущен либо равняется -1, будут заменены все вхождения шаблона.
Replacement может содержать ссылки вида \\n либо (начиная с PHP 4.0.4) $n, причем последний вариант предпочтительней. Каждая такая ссылка, будет заменена на подстроку, соответствующую n’нной заключенной в круглые скобки подмаске. n может принимать значения от 0 до 99, причем ссылка \\0 (либо $0) соответствует вхождению всего шаблона. Подмаски нумеруются слева направо, начиная с единицы.
При использовании замены по шаблону с использованием ссылок на подмаски может возникнуть ситуация, когда непосредственно за маской следует цифра. В таком случае нотация вида \\n приводит к ошибке: ссылка на первую подмаску, за которой следует цифра 1, запишется как \\11, что будет интерпретировано как ссылка на одиннадцатую подмаску. Это недоразумение можно устранить, если воспользоваться конструкцией \$<1>1, указывающей на изолированную ссылку на первую подмаску, и следующую за ней цифру 1.
Результатом работы этого примера будет:
Если во время выполнения функции были обнаружены совпадения с шаблоном, будет возвращено измененное значение subject, в противном случае будет возвращен исходный текст subject.
Первые три параметра функции preg_replace() могут быть одномерными массивами. В случае, если массив использует ключи, при обработке массива они будут взяты в том порядке, в котором они расположены в массиве. Указание ключей в массиве для pattern и replacement не является обязательным. Если вы все же решили использовать индексы, для сопоставления шаблонов и строк, участвующих в замене, используйте функцию ksort() для каждого из массивов.
В случае, если параметр subject является массивом, поиск и замена по шаблону производятся для каждого из его элементов. Возвращаемый результат также будет массивом.
В случае, если параметры pattern и replacement являются массивами, preg_replace() поочередно извлекает из обоих массивов по паре элементов и использует их для операции поиска и замены. Если массив replacement содержит больше элементов, чем pattern, вместо недостающих элементов для замены будут взяты пустые строки. В случае, если pattern является массивом, а replacement — строкой, по каждому элементу массива pattern будет осущесвтлен поиск и замена на pattern (шаблоном будут поочередно все элементы массива, в то время как строка замены остается фиксированной). Вариант, когда pattern является строкой, а replacement — массивом, не имеет смысла.
Модификатор /e меняет поведение функции preg_replace() таким образом, что параметр replacement после выполнения необходимых подстановок интерпретируется как PHP-код и только после этого используется для замены. Используя данный модификатор, будьте внимательны: параметр replacement должен содержать корректный PHP-код, в противном случае в строке, содержащей вызов функции preg_replace(), возникнет ошибка синтаксиса.
Пример кода: Замена по нескольким шаблонам
Этот пример выведет:
Пример кода: Использование модификатора /e
Пример кода: Преобразует все HTML-теги к верхнему регистру
preg_replace_callback
Функция preg_replace_callback — Выполняет поиск по регулярному выражению и замену с использованием функции обратного вызова
mixed preg_replace_callback (mixed pattern, callback callback, mixed subject [, int limit])
Поведение этой функции во многом напоминает preg_replace(), за исключением того, что вместо параметра replacement необходимо указывать callback функцию, которой в качестве входящего параметра передается массив найденных вхождений. Ожидаемый результат — строка, которой будет произведена замена.
Пример кода
preg_split
Функция preg_split — Разбивает строку по регулярному выражению
array preg_split (string pattern, string subject [, int limit [, int flags]])
Возвращает массив, состоящий из подстрок заданной строки subject, которая разбита по границам, соответствующим шаблону pattern.
В случае, если параметр limit указан, функция возвращает не более, чем limit подстрок. Специальное значение limit, равное -1, подразумевает отсутствие ограничения, это весьма полезно для указания еще одного опционального параметра flags.
flags может быть произвольной комбинацией следующих флагов (соединение происходит при помощи оператора ‘|’):
PREG_SPLIT_NO_EMPTY
В случае, если этот флаг указан, функция preg_split() вернет только непустые подстроки.
PREG_SPLIT_DELIM_CAPTURE
В случае, если этот флаг указан, выражение, заключенное в круглые скобки в разделяющем шаблоне, также извлекается из заданной строки и возвращается функцией. Этот флаг был добавлен в PHP 4.0.5.
PREG_SPLIT_OFFSET_CAPTURE
В случае, если этот флаг указан, для каждой найденной подстроки, будет указана ее позиция в исходной строке. Необходимо помнить, что этот флаг меняет формат возвращаемых данных: каждое вхождение возвращается в виде массива, в нулевом элементе которого содержится найденная подстрока, а в первом — смещение.
Примеры кода
В случае, если после открывающей круглой скобки следует «?:«, захват строки не происходит, и текущая подмаска не нумеруется. Например, если строка «the white queen» сопоставляется с шаблоном the ((?:red|white) (king|queen)), будут захвачены подстроки «white queen» и «queen», и они будут пронумерованы 1 и 2 соответственно:
Регулярные выражения PHP
Что такое регулярные выражения?
PHP regexp — это мощный алгоритм сопоставления шаблонов, которое может быть выполнено в одном выражении. Регулярные выражения PHP используют арифметические операторы ( такие как +, -, ^ ) для создания сложных выражений.
Для чего используются регулярные выражения:
- Регулярные выражения упрощают идентификацию строковых данных путем вызова одной функции. Это экономит время при составлении кода;
- При проверке введенных пользователем данных, таких как адрес электронной почты, домен сайта, номер телефона, IP-адрес ;
- Выделение ключевых слов в результатах поиска;
- Регулярные выражения могут использоваться для идентификации тегов и их замены.
Регулярные выражения в PHP
PHP содержит встроенные функции, которые позволяют работать с регулярными выражениями. Теперь рассмотрим часто используемые функции регулярных выражений PHP .
- preg_match — используется для выполнения сопоставления с шаблоном строки. Она возвращает true , если совпадение найдено, и false , если совпадение не найдено;
- preg_split — используется для разбивки строки по шаблону, результат возвращается в виде числового массива;
- preg_replace – используется для поиска по шаблону и замены на указанную строку.
Ниже приведен синтаксис функций регулярных выражений, таких как preg_match , preg_split или PHP regexp replace :
«имя_функции» — это либо preg_match , либо preg_split , либо preg_replace .
«/…/» — косые черты обозначают начало и конец регулярного выражения.
«‘/шаблон/’» — шаблон, который нам нужно сопоставить.
«объект» — строка, с которой нужно сопоставлять шаблон.
Теперь рассмотрим практические примеры использования упомянутых выше функций.
Preg_match
В первом примере функция preg_match используется для выполнения простого сопоставления шаблоном для слова guru в заданном URL-адресе .
В приведенном ниже коде показан вариант реализации данного примера:
Рассмотрим ту часть кода, которая отвечает за вывод «preg_match (‘/ guru /’, $ my_url)» .
«preg_match(…)» — функция PHP match regexp .
«‘/Guru/’» — шаблон регулярного выражения.
«$My_url» — переменная, содержащая текст, с которым нужно сопоставить шаблон.
Preg_split
Рассмотрим другой пример, в котором используется функция preg_split .
Мы возьмем фразу и разобьем ее на массив; шаблон предназначен для поиска единичного пробела:
Preg_replace
Рассмотрим функцию preg_replace , которая выполняет сопоставление с шаблоном и заменяет найденный результат другой строкой.
Приведенный ниже код ищет в строке слово guru . Он заменяет его кодом css , который задает цвет фона:
Метасимволы
В приведенных выше примерах использовались простые шаблоны. Метасимволы позволяют выполнять более сложные сопоставления шаблонов PHP regexp , такие как проверка адреса электронной почты. Рассмотрим часто используемые метасимволы.
Метасимвол | Описание | Пример |
. | Обозначает любой единичный символ, кроме символа новой строки. | /./ — все, что содержит один символ. |
^ | Обозначает начало строки, не включая символ /. | /^PH/ — любая строка, которая начинается с PH. |
$ | Обозначает шаблон в конце строки. | /com$/ — guru99.com,yahoo.com и т.д. |
* | Обозначает любое количество символов, ноль или больше. | /com*/ — computer, communication и т.д. |
+ | Требуется вхождение перед метасимволом символа (ов) хотя бы один раз. | /yah+oo/ — yahoo. |
Символ экранирования. | /yahoo+.com/ — воспринимает точку, как дословное значение. | |
[…] | Класс символов. | /[abc]/ — abc. |
a-z | Обозначает строчные буквы. | /a-z/ — cool, happy и т.д. |
A-Z | Обозначает заглавные буквы. | /A-Z/ — WHAT, HOW, WHY и т.д. |
0-9 | Обозначает любые цифры от 0 до 9. | /0-4/ — 0,1,2,3,4. |
Теперь рассмотрим сложный PHP regexp пример, в котором проверяется валидность адреса электронной почты:
Результат: адрес электронной почты [email protected] является валидным.
Пояснение шаблона «[/^[a-zA-Z0-9._-][email protected][a-zA-Z0-9-]+.[a-zA-Z.]<2,5>$/] «
«‘/…/’» начинает и завершает регулярное выражение.
«^[a-zA-Z0-9._-]» соответствует любым буквам в нижнем или верхнем регистре, цифрам от 0 до 9 и точкам, подчеркиваниям или тире.
«[email protected][a-zA-Z0-9-]» соответствует символу @ , за которым следуют буквы в нижнем или верхнем регистре, цифры от 0 до 9 или дефисы.
«+.[a-zA-Z.]<2,5>$/» указывает точку, используя обратную косую черту, затем должны следовать любые буквы в нижнем или верхнем регистре, количество символов в конце строки должно быть от 2 до 5.
Метасимволы являются полезными, когда речь идет о сопоставлении на соответствие шаблонам.
Заключение
- PHP regexp — это алгоритм поиска по шаблону;
- Регулярные выражения полезны при выполнении проверок валидности, создании HTML-шаблонов , которые распознают теги и т. д.;
- PHP имеет встроенные функции для работы с регулярными выражениями: preg_match , preg_split и preg_replace ;
- Метасимволы позволяют создавать сложные шаблоны.
Данная публикация представляет собой перевод статьи « PHP Regular Expressions » , подготовленной дружной командой проекта Интернет-технологии.ру
Урок 1. Знакомство с регулярными выражениями
В этом уроке вы узнаете, что такое регулярные выражения и что они могут делать.
Назначение регулярных выражений
Регулярные выражения (regular expressions), или сокращенно regex — инструментальные средства, и подобно всем инструментальным средствам, регулярные выражения предназначены для решения очень конкретных проблем. Чтобы узнать, что такое регулярные выражения и что они делают, лучше всего познакомиться с проблемами, которые решаются с их помощью.
Рассмотрим следующие сценарии.
- Вы ищете файл, содержащий текст car (независимо от регистра), но не хотите указать местонахождение текста car — в середине, в начале или в конце слова (например, scar, carry и incarcerate).
- Вы динамически генерируете Web-страницу (используя сервер приложений) и должны отобразить текст, найденный в базе данных. Текст может содержать URL, и вы хотите, чтобы на сгенерированной странице URL можно было активизировать щелчком (так что вместо того, чтобы генерировать только текст, вы хотите сгенерировать правильный HTML-тег . .
- Вы создаете Web-страницу, содержащую форму. Форма запрашивает у пользователя разную информацию, включая и адрес электронной почты. Вы должны проверить, что указанные адреса имеют правильный формат (т.е. что они являются синтаксически правильными (допустимыми)).
- Вы редактируете исходный текст и должны заменить все вхождения слова size на iSize, но замену хотите выполнять только для слова size и не хотите заменять вхождения size там, где они выступают как часть другого слова.
- Вы отображаете список всех файлов в файловой системе компьютера и хотите отфильтровать этот список так, чтобы определить местонахождение только тех файлов, которые содержат текст Application.
- Вы импортируете данные в приложение. Данные разграничены знаками табуляции, и ваше приложение поддерживает файлы формата CSV (одна строка данных в строке текста, значения разделены запятыми, каждое значение можно заключить в кавычки).
- Вы должны найти в файле определенный текст, но только в определенном местоположении (например, в начале строки или в конце предложения).
Все эти сценарии представляют собой обычные программистские задачи. И все они могут быть решены почти на любом языке, в котором есть условные выражения и операции над строками. Но насколько сложно решить эти задачи? Вам понадобится в цикле перебирать слова или символы по одному, выполнять все типы условных операторов, отслеживать массу флажков, чтобы убедиться, что вы нашли то, что искали, или чтобы быть уверенными, что вы не нашли искомый текст, проверять всевозможные пробельные и специальные символы, и по ходу дела решить еще много подобных задач. И вы должны были бы сделать это все вручную.
Но вы можете использовать регулярные выражения. Каждая из предыдущих задач может быть решена с помощью подходящих инструкций, записанных в кратких строках, содержащих текст и специальные инструкции-команды, которые могут выглядеть следующим образом:
Как используются регулярные выражения
Просмотрите сценарии еще раз и обратите внимание, что все они относятся к одному из двух типов: либо отыскивается местонахождение информации (поиск текста), либо информация найдена и редактируется (выполняются замены). Фактически это и есть то, для чего используются регулярные выражения: поиск и замена. Каждое регулярное выражение либо ищет текст (выполняет операцию поиска) или ищет и заменяет текст (выполняет операцию замены).
Поиск с помощью регулярных выражений
Регулярные выражения используются для поиска тек¬ста, причем разыскиваемый текст может иметь разный вид, как при поиске саг в описанном ранее сценарии. Для начинающих отмечу, что задача может состоять в том, чтобы найти car или CAR или CaR ; это совсем простая часть (многие средства поиска способны выполнять поиск независимо от регистра). Более сложная часть состоит в том, чтобы гарантировать, что найденное вхождение car не входит в scar , carry или incarcerate . Некоторые более сложные редакторы имеют опции Match Only Whole Word (Найти только слово целиком), но во многих эта опция отсутствует, и вы не можете делать такие замены в редактируемом документе. Решает проблему поиска использование регулярного выражения, а не просто текста car .
Стоит заметить, что проверка на равенство (т.е. решение задачи вроде: соответствует ли указанный пользователем адрес электронной почты данному регулярному выражению?) и есть операция поиска. Выполняется операция поиска во всей введенной пользователем строке (а не операция поиска подстроки).
Замены с помощью регулярных выражений
Поиск с помощью регулярных выражений — очень мощное и очень полезное средство, причем совсем не трудно научиться применять его. Поэтому во многих уроках приводятся примеры выполнения операций поиска. Однако реальная польза регулярных выражений состоит именно в операциях замены, типа тех, что встречались в более раннем сценарии, в котором текстовый URL заменялся настоящим URL, активизирующимся щелчком мыши. Для начинающих отмечу, что для этого требуется определить местонахождение URL в тексте (возможно, для этого нужно выполнить поиск строк, которые начинаются с http:// или https:// и заканчиваются точкой, запятой или пробельным символом). Затем потребуется заменить найденный URL с двумя вхождениями найденной строки встроенным HTML-кодом так, чтобы
Опция Search and Replace (Найти и заменить) в большинстве приложений не может выполнять операции замены такого типа, но решение этой задачи — невероятно простое регулярное выражение.
Так что же такое регулярное выражение?
Теперь, когда вы знаете, для чего используются регулярные выражения, дадим их определение. Попросту говоря, регулярные выражения — это строки, которые используются для поиска и обработки текста. Регулярные выражения записываются на языке регулярных выражений, т.е. на специализированном языке, разработанном и предназначенном для решения задач: поиска и замены текста. Подобно любому языку, язык регулярных выражений имеет специальный синтаксис и команды, которые вам предстоит освоить, и именно их вы будете изучать по данной книге.
Язык регулярных выражений — не полноценный язык программирования. Это обычно даже не программа или утилита, которую можно установить и использовать. Чаще всего регулярные выражения представляют собой миния-зыки, которые встроены в другие языки или программы. Хорошая новость состоит в том, что практически любой современный приличный язык или инструмент поддерживает регулярные выражения. Плохая новость в том, что сам по себе язык регулярных выражений не собирается искать что-нибудь подобно другим применяемым вами языкам или инструментам. Язык регулярных выражений — язык в себе, а совсем не интуитивно понятный язык для выполнения каких-либо очевидных операций.
Приведем примеры правильных (допустимых) регулярных выражений (их смысл вы вскоре поймете):
Важно уяснить, что синтаксис — самая простая часть в освоении регулярных выражений. Что действительно трудно, так это научиться применять этот синтаксис и разбивать задачи на подзадачи, решения которых находятся с помощью регулярных выражений. Этому нельзя научиться, просто читая книгу; подобно любому языку, вы овладеете языком регулярных выражений, выполняя разнообразные упражнения, а мастерство придет с практикой.
Использование регулярных выражений
Как уже отмечалось, для регулярных выражений нет никакой особой программы; это не приложение, которое вы выполняете, и не программное обеспечение, которое вы можете купить или загрузить. Совсем наоборот, язык регулярных выражений реализован в большом количестве программных изделий, языков, утилит и сред разработки.
То, как используются регулярные выражения и какие функциональные возможности регулярных выражений экспортируются, зависит от используемого вами приложения. Иногда в приложениях для применения регулярных выражений используются меню и диалоговые окна, а в некоторых языках программирования имеются функции или классы объектов, которые экспортируют функциональные возможности регулярных выражений.
Кроме того, не все реализации регулярных выражений одинаковы. Часто есть очень тонкие (а иногда и не очень тонкие) различия в синтаксисе и возможностях регулярных выражений.
Чтобы вам было легче освоить материал, вы можете загрузить приложение Regular Expression Tester (испытатель регулярных выражений) с Web-страницы этой книги (http://www.forta.com/books/0672325667/). Данное приложение имеет версии для использования в популярных серверах приложений и языках, а также прямо в JavaScript.
Перед началом
Прежде чем приступить к применению регулярных выражений, примите во внимание следующее.
- При использовании регулярных выражений почти всегда есть несколько решений любой задачи. Некоторые решения более просты, некоторые более быстрые, некоторые более удобны для переноса, а некоторые более удобны для обобщения. Редко есть один единственно правильный способ записи регулярного выражения (подразумевается, конечно, что при всех формах записи поставленная задача решается правильно).
- Как уже указывалось, существуют различия в реализации регулярных выражений. Насколько возможно, примеры и информация в уроках этой книги применимы ко всем главным реализациям, причем различия и несовместимости отмечаются особо.
- Как и для любого языка, ключ к освоению регулярных выражений — практика, практика и еще раз практика.
Резюме
Регулярные выражения — одно из самых мощных инструментальных средств обработки текстов. Язык регулярных выражений применяется для записи регулярных выражений (фактически, записанную строку и называют регулярным выражением), причем регулярные выражения используются для выполнения операций замены и поиска.
Регулярные выражения для новичков
Задачи и их разборы с javascript.ru; в статье использованы комиксы xkcd.
Что такое регулярные выражения?
Если вам когда-нибудь приходилось работать с командной строкой, вы, вероятно, использовали маски имён файлов. Например, чтобы удалить все файлы в текущей директории, которые начинаются с буквы “d”, можно написать rm d* .
Регулярные выражения представляют собой похожий, но гораздо более сильный инструмент для поиска строк, проверки их на соответствие какому-либо шаблону и другой подобной работы. Англоязычное название этого инструмента — Regular Expressions или просто RegExp. Строго говоря, регулярные выражения — специальный язык для описания шаблонов строк.
Реализация этого инструмента различается в разных языках программирования, хоть и не сильно. В данной статье мы будем ориентироваться в первую очередь на реализацию Perl Compatible Regular Expressions.
Основы синтаксиса
В первую очередь стоит заметить, что любая строка сама по себе является регулярным выражением. Так, выражению Хаха , очевидно, будет соответствовать строка “Хаха” и только она. Регулярные выражения являются регистрозависимыми, поэтому строка “хаха” (с маленькой буквы) уже не будет соответствовать выражению выше.
«Росбанк», Москва, до 60 000 ₽ (до налогов)
Однако уже здесь следует быть аккуратным — как и любой язык, регулярные выражения имеют спецсимволы, которые нужно экранировать. Вот их список: . ^ $ * + ? < >[ ] \ | ( ) . Экранирование осуществляется обычным способом — добавлением \ перед спецсимволом.
Набор символов
Предположим, мы хотим найти в тексте все междометия, обозначающие смех. Просто Хаха нам не подойдёт — ведь под него не попадут “Хехе”, “Хохо” и “Хихи”. Да и проблему с регистром первой буквы нужно как-то решить.
Здесь нам на помощь придут наборы — вместо указания конкретного символа, мы можем записать целый список, и если в исследуемой строке на указанном месте будет стоять любой из перечисленных символов, строка будет считаться подходящей. Наборы записываются в квадратных скобках — паттерну [abcd] будет соответствовать любой из символов “a”, “b”, “c” или “d”.
Внутри набора большая часть спецсимволов не нуждается в экранировании, однако использование \ перед ними не будет считаться ошибкой. По прежнему необходимо экранировать символы “\” и “^”, и, желательно, “]” (так, [][] обозначает любой из символов “]” или «[», тогда как [[]х] – исключительно последовательность “[х]”). Необычное на первый взгляд поведение регулярок с символом “]” на самом деле определяется известными правилами, но гораздо легче просто экранировать этот символ, чем их запоминать. Кроме этого, экранировать нужно символ «-», он используется для задания диапазонов (см. ниже).
Если сразу после [ записать символ ^ , то набор приобретёт обратный смысл — подходящим будет считаться любой символ кроме указанных. Так, паттерну [^xyz] соответствует любой символ, кроме, собственно, “x”, “y” или “z”.
Итак, применяя данный инструмент к нашему случаю, если мы напишем [Хх][аоие]х[аоие] , то каждая из строк “Хаха”, “хехе”, “хихи” и даже “Хохо” будут соответствовать шаблону.
Предопределённые классы символов
Для некоторых наборов, которые используются достаточно часто, существуют специальные шаблоны. Так, для описания любого пробельного символа (пробел, табуляция, перенос строки) используется \s , для цифр — \d , для символов латиницы, цифр и подчёркивания “_” — \w .
Если необходимо описать вообще любой символ, для этого используется точка — . . Если указанные классы написать с заглавной буквы ( \S , \D , \W ) то они поменяют свой смысл на противоположный — любой непробельный символ, любой символ, который не является цифрой, и любой символ кроме латиницы, цифр или подчёркивания соответственно.
Также с помощью регулярных выражений есть возможность проверить положение строки относительно остального текста. Выражение \b обозначает границу слова, \B — не границу слова, ^ — начало текста, а $ — конец. Так, по паттерну \bJava\b в строке “Java and JavaScript” найдутся первые 4 символа, а по паттерну \bJava\B — символы c 10-го по 13-й (в составе слова “JavaScript”).
Комикс про регулярные выражения с xkcd.ru
Диапазоны
У вас может возникнуть необходимость обозначить набор, в который входят буквы, например, от “б” до “ф”. Вместо того, чтобы писать [бвгдежзиклмнопрстуф] можно воспользоваться механизмом диапазонов и написать [б-ф] . Так, паттерну x[0-8A-F][0-8A-F] соответствует строка “xA6”, но не соответствует “xb9” (во-первых, из-за того, что в диапазоне указаны только заглавные буквы, во-вторых, из-за того, что 9 не входит в промежуток 0-8).
Механизм диапазонов особенно актуален для русского языка, ведь для него нет конструкции, аналогичной \w . Чтобы обозначить все буквы русского алфавита, можно использовать паттерн [а-яА-ЯёЁ] . Обратите внимание, что буква “ё” не включается в общий диапазон букв, и её нужно указывать отдельно.
Квантификаторы (указание количества повторений)
Вернёмся к нашему примеру. Что, если в “смеющемся” междометии будет больше одной гласной между буквами “х”, например “Хаахаааа”? Наша старая регулярка уже не сможет нам помочь. Здесь нам придётся воспользоваться квантификаторами.
Квантификатор | Число повторений | Пример | Подходящие строки |
Ровно n раз | Ха<3>ха | Хаааха | |
От m до n включительно | Ха<2,4>ха | Хаа, Хааа, Хааааха | |
Не менее m | Ха<2,>ха | Хааха, Хаааха, Хааааха и т. д. | |
Не более n | Ха<,3>ха | Хха, Хаха, Хааха, Хаааха |
Обратите внимание, что квантификатор применяется только к символу, который стоит перед ним.
Некоторые часто используемые конструкции получили в языке регулярных выражений специальные обозначения:
Квантификатор | Аналог | Значение |
? | Ноль или одно вхождение | |
* | Ноль или более | |
+ | Одно или более |
Таким образом, с помощью квантификаторов мы можем улучшить наш шаблон для междометий до [Хх][аоеи]+х[аоеи]* , и он сможет распознавать строки “Хааха”, “хееееех” и “Хихии”.
Ленивая квантификация
Предположим, перед нами стоит задача — найти все HTML-теги в строке
Очевидное решение здесь не сработает — оно найдёт всю строку целиком, т.к. она начинается с тега абзаца и им же заканчивается. То есть содержимым тега будет считаться строка
Это происходит из-за того, что по умолчанию квантификатор работают по т.н. жадному алгоритму — старается вернуть как можно более длинную строку, соответствующую условию. Решить проблему можно двумя способами. Первый — использовать выражение ]*> , которое запретит считать содержимым тега правую угловую скобку. Второй — объявить квантификатор не жадным, а ленивым. Делается это с помощью добавления справа к квантификатору символа ? . Т.е. для поиска всех тегов выражение обратится в .
Ревнивая квантификация
Иногда для увеличения скорости поиска (особенно в тех случаях, когда строка не соответствует регулярному выражению) можно использовать запрет алгоритму возвращаться к предыдущим шагам поиска для того, чтобы найти возможные соответствия для оставшейся части регулярного выражения. Это называется ревнивой квантификацией. Квантификатор делается ревнивым с помощью добавления к нему справа символа + . Ещё одно применение ревнивой квантификации — исключение нежелательных совпадений. Так, паттерну ab*+a в строке “ababa” будут соответствовать только первые три символа, но не символы с третьего по пятый, т.к. символ “a”, который стоит на третьей позиции, уже был использован для первого результата.
Скобочные группы
Для нашего шаблона “смеющегося” междометия осталась самая малость — учесть, что буква “х” может встречаться более одного раза, например, “Хахахахааахахооо”, а может и вовсе заканчиваться на букве “х”. Вероятно, здесь нужно применить квантификатор для группы [аиое]+х , но если мы просто напишем [аиое]х+ , то квантификатор + будет относиться только к символу “х”, а не ко всему выражению. Чтобы это исправить, выражение нужно взять в круглые скобки: ([аиое]х)+ .
Таким образом, наше выражение превращается в [Хх]([аиое]х?)+ — сначала идёт заглавная или строчная “х”, а потом произвольное ненулевое количество гласных, которые (возможно, но не обязательно) перемежаются одиночными строчными “х”. Однако это выражение решает проблему лишь частично — под это выражение попадут и такие строки, как, например, “хихахех” — кто-то может быть так и смеётся, но допущение весьма сомнительное. Очевидно, мы можем использовать набор из всех гласных лишь единожды, а потом должны как-то опираться на результат первого поиска. Но как?…
Запоминание результата поиска по группе (обратная связь)
Оказывается, результат поиска по скобочной группе записывается в отдельную ячейку памяти, доступ к которой доступен для использования в последующих частях регулярного выражения. Возвращаясь к задаче с поиском HTML-тегов на странице, нам может понадобиться не только найти теги, но и узнать их название. В этом нам может помочь регулярное выражение .
Результат поиска по всем регулярному выражению: “
”.
Результат поиска по первой группе: “p”, “b”, “/b”, “i”, “/i”, “/i”, “/p”.
На результат поиска по группе можно ссылаться с помощью выражения \n , где n — цифра от 1 до 9. Например выражению (\w)(\w)\1\2 соответствуют строки “aaaa”, “abab”, но не соответствует “aabb”.
Если выражение берётся в скобки только для применения к ней квантификатора (не планируется запоминать результат поиска по этой группе), то сразу после первой скобки стоит добавить ?: , например (?:[abcd]+\w) .
С использованием этого механизма мы можем переписать наше выражение к виду [Хх]([аоие])х?(?:\1х?)* .
Перечисление
Чтобы проверить, удовлетворяет ли строка хотя бы одному из шаблонов, можно воспользоваться аналогом булевого оператора OR, который записывается с помощью символа | . Так, под шаблон Анна|Одиночество попадают строки “Анна” и “Одиночество” соответственно. Особенно удобно использовать перечисления внутри скобочных групп. Так, например (?:a|b|c|d) полностью эквивалентно [abcd] (в данном случае второй вариант предпочтительнее в силу производительности и читаемости).
С помощью этого оператора мы сможем добавить к нашему регулярному выражению для поиска междометий возможность распознавать смех вида “Ахахаах” — единственной усмешке, которая начинается с гласной: [Хх]([аоие])х?(?:\1х?)*|[Аа]х?(?:ах?)+
Полезные сервисы
Потренироваться и / или проверить своё регулярное выражение на каком-либо тексте без написания кода можно с помощью таких сервисов, как RegExr, Regexpal или Regex101. Последний, вдобавок, приводит краткие пояснения к тому, как регулярка работает.
Разобраться, как работает регулярное выражение, которое попало к вам в руки, можно с помощью сервиса Regexper — он умеет строить понятные диаграмы по регулярному выражению.
RegExp Builder — визуальный конструктор функций JavaScript для работы с регулярными выражениями.
Больше инструментов можно найти в нашей подборке.
Задания для закрепления
Найдите время
Время имеет формат часы:минуты. И часы, и минуты состоят из двух цифр, пример: 09:00. Напишите регулярное выражение для поиска времени в строке: “Завтрак в 09:00”. Учтите, что “37:98” – некорректное время.
Регулярные выражения для чайников
Что такое регулярные выражения?
В народе: регэкспы, регулярки.
По-простому — это выражения для поиска и замены подстроки по шаблону.
В PHP используется название PCRE (Perl Compatible Regular Expressions —
перл совместимые регулярные выражения). В этой статье я постараюсь раскрыть
потенциал это мощного инструмента программиста. Не пытайтесь понять все сразу,
впитывайте порциями и приходите за добавкой.
Начнем
// наша строка для испытаний
$string = ‘abcdefghijklmnopqrstuvwxyz0123456789’ ;
Если нам нужно просто узнать есть ли шаблон ‘abc’ в строке $string
мы можем набросать такой код:
echo preg_match ( «/abc/» , $string ) ;
?>
Этот код выведет ‘1’. Потому что он нашел 1 (одно) вхождение шаблона в строке.
Если шаблон в строке не обнаружен, preg_match вернет 0. При нахождении первого вхождения,
функция сразу возвращает результат! Дальнейший поиск не продолжается (см. preg_match_all)
Нахождение начала строки
Теперь мы желаем узнать, начинается ли строка с ‘abc’.
Символ начала строки в регулярках — ‘^’ (caret — знак вставки).
// тест на начало строки
if ( preg_match ( «/^abc/» , $string ) )
<
// окей, строка начинается с абс
echo ‘The string begins with abc’ ;
>
else
<
echo ‘это фэйл’ ;
>
?>
Пример выведет:
The string begins with abc
Оборачивающие слэши — разделители, содержат регуряное выражение. Это могут быть любые парные символы,
например @[email protected], #regex#, /regex/ и .т.п.
Символ ^ сразу после первого разделителя указывает что выражение начинается сначала строки и НИКАК иначе.
Что делать с регистром символов (строчные-прописные)
Перепишем код, чтобы он искал строку ‘ABC’:
Скрипт вернет:
Не думаю
Все потому что поиск регистро-зависимый. Шаблон ‘abc’ не тоже самое что ‘ABC’.
Чтобы найти оба варианта, нужно использовать модификатор. В регулярных выражениях
для этого применяется модификатор ‘i’, который нужно указать за закрывающим разделителем
регулярного выражения.
if ( preg_match ( «/^ABC/i» , $string ) ) <
echo ‘Совпадение, строка начинается с abc’ ;
> else <
echo ‘Не думаю’ ;
>
?>
Теперь скрипт найдет паттерн ‘abc’. Также теперь будут попадать под шаблон
строки вида abc, ABC, Abc, aBc, и т.п.
Позже будет рассказано подробнее о модификаторах.
Как указать в паттерне конец строки
Делается это также как и в случае с поиском начала строки.
Распространенная ошибка, допускаемя многими прогерами — использование символа $ для указания конца строки в шаблоне.
Это неверно, правильное решение — использовать утверждение \z. Посмотрите на этот код
Сниппет вернет true, потому что $ = \Z, что в свою очередь можно описать выражением (?=\z|\n\z).
Когда нам нужно получить в результате строку без «разделителей строк», $ не должен использоваться.
Также $ совпададет больше одного раза с модификатором /m, в противоположность \z. Изменим немного код,
удалим каретку (^) в начале паттерна и добавим \z в конце, также уберем зависимость от регистра модификатором /i.
// паттерн в конце строки?
if ( preg_match ( «/89 \z /i» , $string ) ) <
echo ‘Совпадение, строка заканчивается на 89’ ;
> else <
echo ‘Не думаю’ ;
>
?>
Результат скрипта:
>> Совпадение, строка заканчивается на 89
Потому что мы определили конец строки 89. Вот так.
Мета символы
Ранее мы поэкспериментировали с простыми регулярками. Познакомились с кареткой (^) и долларом ($)/
Эти символы имееют особенное значение. Каретка (^) обозначает начало страки и доллар ($) — ее конец.
Такие символы в купе с остальными специальными называются мета символами (meta characters).
Список мета символов в регулярных выражениях:
Разберем все символы на примерах.
Если вам нужно составить шаблон в котором содержится такой символ, его необходимо экранировать (см. preg_quote)
Например шаблон: «1+1», нужно записать как-то так:
// образец
$string = ‘1+1=2’ ;
if ( preg_match ( «/^1 \+ 1/i» , $string ) ) <
// yep
echo ‘The string begins with 1+1’ ;
> else <
// nope
echo ‘Не думаю’ ;
>
?>
Результат скрипта:
The string begins with 1+1
Потому что интерпретатор проигнорировал специальное значение символа «+», обозначенного символом экранирования «\» (бэкслэш).
Если бы мы не добавили экран к плюсу, то preg_match(«/^1+1/i», $string) не нашло бы совпадений с шаблоном.
Сам бэкслэш в свою очередь тоже нужно экранировать, если мы ищем именно этот символ «\\».
Что означают остальные мета символы
Квадратные скобки [ ] обозначают «строковой класс».
Символьный класс. Это просто набор символов, которые должны совпасть в искомой строке.
Они могут записываться индивидуально (по одному):
Или как диапазон, разделенный символом «-«:
// Ищем шаблон
echo preg_match ( «/b[aoiu]g/» , $string , $matches ) ;
Результат скрипта:
return 1
Потому что preg_match() нашел совпадение.
Этот код также найдет совпадение со строками ‘bag’ ‘bog’ ‘big’, но не с ‘beg’.
Диапазон символов [a-f] равнозначен такой записи [abcdef]. Словами формулируется так [от ‘a’ до ‘f’].
Еще раз повторю, выражения регистрозависимые, и [A-F] не тоже самое что и [a-f].
Мета символы не работыют внутри классов, поэтому их не нужно экранировать внутри квадратных скобок [. ].
Например класс [abcdef$] совпадет с символами a b c d e f $. Доллар ($) внутри класса — это простой бакс знак доллара без какого либо специального мета-свойства.
Есть правда исключения из правил:
Одна из полезных функций регулярных выражений — возможность указать шаблон НЕ совпадающий с диапазоном символов.
Чтобы это сделать, нужно использовать каретку (^) первым символом класса.
Найдем любые символы, кроме «b»:
// осуществляем поиск
preg_match ( «/[^b]/» , $string , $matches ) ;
// выведем все совпадения в цикле foreach
foreach ( $matches as $key => $value ) <
echo $key . ‘ -> ‘ . $value ;
>
?>
Результат скрипта:
0 -> a
Здесь preg_match() нашел первое совпадение с шаблоном /[^b]/.
Изменим скрипт и используем preg_match_all() для нахождения всех вхождений соответствующих шаблону /[^b]/.
// ищем ВСЕ совпадения
preg_match_all ( «/[^b]/» , $string , $matches ) ;
// выведем все совпадения в цикле foreach
foreach ( $matches [ 0 ] as $value ) <
echo $value ;
>
?>
Результат скрипта:
acefghijklmnopqrstuvwxyz0123456789
Выведет все символы, которые НЕ совпадают с шаблоном «b».
Так мы можем отфильтровать все цифры в строке:
// все символы не являющиеся цифрами от 0 до 9
preg_match_all ( «/[^0-9]/» , $string , $matches ) ;
foreach ( $matches [ 0 ] as $value ) <
echo $value ;
>
?>
Результат скрипта:
abcefghijklmnopqrstuvwxyz
Шаблон [^0-9] расшифровывается как все НЕ включая цифры от 0 до 9.
Продолжаете слушать нашу радиостанцию?
Тогда продолжим.
Метасимвол Бэкслэш (\).
Основное значение — экранирование других метасимволов.
// create a string
$string = ‘This is a [templateVar]’ ;
// try to match our pattern
preg_match_all ( «/[ \[ \] ]/» , $string , $matches ) ;
// loop through the matches with foreach
foreach ( $matches [ 0 ] as $value ) <
echo $value ;
>
?>
Здесь мы хотели найти все символы []. Без экранирования шаблон выглядел бы так — «/[[]]/»,
но мы добавили бэеслэши к скобкам [], чтобы отменить их мета-статус.
Также, к примеру, поступим с путем к файлу.
c:\dir\file.php
В паттерне будем использовать разделитель «\\».
Бэкслэш также ортодоксально используется в строках для указания специальных последовательностей: \n, \r и др.
Еще он неймспейсы разделяет!
Следующий символ «.» (точка) ака «полный стоп».
`Точка` совпадает с любым символом кроме символов разрыва строки \r или \n.
С помощью точки мы можем найти любой одиночный символ, за исключением разрыва строки.
Чтобы точка также совпадала с переводом каретки и разрывом строки, можно использовать флаг /s.
Ищем одиночный символ
$string = ‘sex at noon taxes’ ;
echo preg_match ( «/s.x/» , $string , $matches ) ;
?>
Результат скрипта:
1
Да, да preg_match() нашел одно совпадение. Пример также сработает с sax, six, sox, sux, и s x, но не совпадет с «stix».
Теперь попробуем найти \n.
// create a string
$string = ‘sex’ . » \n » . ‘at’ . » \n » . ‘noon’ . » \n » . ‘taxes’ . » \n » ;
// echo the string
echo nl2br ( $string ) ;
// look for a match
echo preg_match_all ( «/ \s /» , $string , $matches ) ;
Результат скрипта:
sex
at
noon
taxes
4
preg_match_all() нашел 4 совпадения разрыва строки «\n» потому что мы использовали флаг \s. Подробнее про флаге в разделе Спец Последовательностей..
Следующий волшебный символ — звездочка (*) asterisk
Совпадает с НОЛем и/или БОЛЕЕ вхождений шаблона, находящегося перед звездочкой.
* означает опциональный шаблон — допускается что символы могут быть, а могут и отсутствовать в строке.
Так шаблон .* совпадает с любым количеством любых символов. Пример:
// create a string
$string = ‘php’ ;
// look for a match
echo preg_match ( «/ph*p/» , $string , $matches ) ;
Результат скрипта:
1
Нашлось одно совпадение. В примере это один символ «h».
Пример также совпадет также со строкой «pp» (ноль символов «h»), и «phhhp» (три символа «h»).
Добрались до мета символа символа «+»
Плюс почти тоже самое что и звездочка, за исключением того что плюс совпадает с ОДНИМ и БОЛЬШЕ символом.
Так в примере звездочка «*» совпала со строкой ‘pp’, с плюсом «+» такое не пройдет.
// create a string
$string = ‘pp’ ;
// look for a match
echo preg_match ( «/ph+p/» , $string , $matches ) ;
Результат скрипта:
Потому что ни одного символа «h».
Следубщий пациент
Мета символ «?»
Знак вопроса совпадет с НУЛЕМ или ОДНИМ вхождением символа или регулярным выражением,
указанным сразу перед ним. Полезен для указания опциональных символов (которых может и не быть).
Например, телефонный номер в Австралии: 1234-5678.
// create a string
$string = ‘12345678’ ;
// look for a match
echo preg_match ( «/1234-?5678/» , $string , $matches ) ;
Результат скрипта:
1
Потому что -? совпал 0 раз с символом «-«. Изменение строки на «1234-5678» выдаст тот же результат.
Фигурные скобки <>
Указывает на количество совпавших символов или их интервал.
Например, за фразой PHP должно следовать ТОЧНО ТРИ цифры:
// create a string
$string = ‘PHP123’ ;
// look for a match
echo preg_match ( «/PHP[0-9]<3>/» , $string , $matches ) ;
Результат скрипта:
1
Шаблон PHP 0-9(цифры от 0 до 9) <3>(три раза) совпал.
Специальные последовательности
Бэкслэш (\) используется для спец. последовательностей:
* \d — любая цифра (тоже самое что и [0-9])
* \D — любая НЕ цифра ([^0-9])
* \s — все «недосимволы» — пробелы, переводы строки, табуляция ([ \t\n\r\f\v])
* \S — все НЕ «недосимволы» ([^ \t\n\r\f\v])
* \w — все альфа-цифровые символы (буквенно-числовые) ([a-zA-Z0-9_])
* \W — все НЕ альфа-цифровые символы ([^a-zA-Z0-9_])
Итак, используя последофательности (флаги) мы можем сократить наши регулярные выражения
и улучшить их читабельность.
// match our pattern containing a special sequence
preg_match_all ( «/[ \w ]/» , $string , $matches ) ;
// loop through the matches with foreach
foreach ( $matches [ 0 ] as $value ) <
echo $value ;
>
?>
Результат скрипта:
abcefghijklmnopqrstuvwxyz0123456789
Мы нашли (preg_match_all) все цифры и буквы (\w) класса ( [] ).
На следующем примере мы можем убедиться, что строка не содержит чисел.
// create a string
$string = ‘2 bad for perl’ ;
// echo our string
if ( preg_match ( «/^ \d /» , $string ) ) <
echo ‘String begins with a number’ ;
> else <
echo ‘String does not begin with a number’ ;
>
?>
Метасимвол «.» (Точка, полный стоп)
Совпадает один раз с любым символом (кроме разрыва строки)
// create a string
$string = ‘abcdefghijklmnopqrstuvwxyz0123456789’ ;
// try to match any character
if ( preg_match ( «/./» , $string ) ) <
echo ‘The string contains at least on character’ ;
> else <
echo ‘String does not contain anything’ ;
>
?>
Результат скрипта:
The string contains at least on character
Конечно, код содержит хотябы один символ.
Ранее была рассмотрена проблема нахождения символа разрыва строки, потому что «.» не совпадает с таким символом (\n).
Здесь нам на помощь придет флаг \s. Он найдет любой пробельный символ (недосимвол).
Для примера используем \n.
// create a string
$string = ‘sex’ . » \n » . ‘at’ . » \n » . ‘noon’ . » \n » . ‘taxes’ . » \n » ;
// echo the string
echo nl2br ( $string ) ;
// look for a match
echo preg_match_all ( «/ \s /» , $string , $matches ) ;
Результат скрипта:
sex
at
noon
taxes
4
preg_match() нашел 4 совпадения перевода строки \n.
Теперь все вместе, хором
Более сложные выражения.
Рассмотрим оператор OR (ИЛИ).
В регулярных выражениях это символ «|» (труба, канал).
Настало время показательного «Hello World» скрипта.
// a simple string
$string = «This is a Hello World script» ;
// try to match the patterns This OR That OR There
echo preg_match ( «/^(This|That|There)/» , $string ) ;
?>
Усложним задачу: попытаемся найти одновременно Hello или Jello в строке.
// a simple string
$string = «This is a Hello World script» ;
// try to match the patterns Jello or Hello
if ( ! preg_match ( «/(Je|He)llo/» , $string ) ) <
echo ‘Pattern not found’ ;
> else <
echo ‘pattern found’ ;
>
?>
Хотя шаблон совпал, мы не видим какую имеено сроку мы нашли.
Для возвращения найденных результатов в preg_match добавляется третий параметр (&$matches):
// a simple string
$string = «This is a Hello World script» ;
// try to match the patterns Jello or Hello
// put the matches in a variable called matches
preg_match ( «/(Je|He)llo/» , $string , $matches ) ;
// loop through the array of matches and print them
foreach ( $matches as $key => $value ) <
echo $key . ‘->’ . $value . ‘
‘ ;
>
?>
Элемент массив $matches[0] содержит всю совпавшую подстроку (всегда), в примере — Hello.
Последующие элементы содержат последовательно вхождения субпаттернов «()».
$matches[1] совпадает с первым субпатерном. В примере — (Je|He)
Модификаторы и утверждения
Модификаторы изменяют поведения шаблонов регулярных выражений.
i — регистронезависимый (Ignore Case, case insensitive)
U — нежадный поиск (Make search ungreedy)
s — включая перевод строки (Includes New line)
m — мультистрока (Multiple lines)
x — Extended for comments and whitespace
e — Enables evaluation of replacement as PHP code. (preg_replace only)
S — Extra analysis of pattern
b — граница слова (Word Boundry)
B — НЕ граница слова (Not a word boundary)
A — начало шаблона (Start of subject)
Z — конец шаблона или разрыв строки (End of subject or newline at end)
z — конец шаблона (End of subject)
G — первая совпавшая позиция в шаблоне (First matching position in subject)
?>
Простой пример модификатора «i»
// create a string
$string = ‘abcdefghijklmnopqrstuvwxyz0123456789’ ;
// try to match our pattern
if ( preg_match ( «/^ABC/i» , $string ) ) <
echo ‘Совпадение, строка начинается с abc’ ;
> else <
echo ‘Не думаю’ ;
>
?>
?>
Использование модификатора «s»
/*** create a string with new line characters ***/
$string = ‘sex’ . » \n » . ‘at’ . » \n » . ‘noon’ . » \n » . ‘taxes’ . » \n » ;
/*** look for a match */
echo preg_match ( «/sex.at.noon/» , $string , $matches ) ;
Результат скрипта:
«.» не находит символы разрыва строки, добавим модификатор «s»
чтобы это исправить
/*** create a string with new line characters ***/
$string = ‘sex’ . » \n » . ‘at’ . » \n » . ‘noon’ . » \n » . ‘taxes’ . » \n » ;
/*** look for a match using s modifier ***/
echo preg_match ( «/sex.at.noon/s» , $string , $matches ) ;
?>
?>
Результат скрипта:
1
Разрывы строк позволяют нам использовать модификатор «m».
Это улично-магический модификатор. Он принимает строку за однострочнкую с символом разрыва на конце,
даже если в строке на самом деле больше символов разрыва (мультистрока).
Т.е. если в строке нет символов разрыва строк, этот модификатор ничего не значит.
// create a string
$string = ‘sex’ . » \n » . ‘at’ . » \n » . ‘noon’ . » \n » . ‘taxes’ . » \n » ;
// look for a match
if ( preg_match ( «/^noon/im» , $string ) ) <
echo ‘Pattern Found’ ;
> else <
echo ‘Pattern not found’ ;
>
?>
Результат скрипта:
Pattern Found
Конечно регулярное выражение найдет совпадение.
Все что следует после первого символа разрыва строки отбрасывается из-за модификатора «m».
В примере используюся вместе модификаторы «i» и «m», их действие комбинируется.
«x» модификатор позволяет составлять регулярное выражение на нескольких строках,
что повышает его читабельность и позволяет добавлять комментарии внутри шаблона.
// create a string
$string = ‘sex’ . » \n » . ‘at’ . » \n » . ‘noon’ . » \n » . ‘taxes’ . » \n » ;
// create our regex using comments and store the regex
// in a variable to be used with preg_match
$regex = ‘
/ # opening double quote
^ # caret means beginning of the string
noon # the pattern to match
/imx
‘ ;
// look for a match
if ( preg_match ( $regex , $string ) ) <
echo ‘Pattern Found’ ;
> else <
echo ‘Pattern not found’ ;
>
?>
Код в пояснениях не нуждается, он просто демонстрирует как можно вставить комментарии и
написать выражение в несколько строк.
Модификатор «e»
Спец млжификатор, который изменяет выполнение сопоставления шаблону. Ниже будет выделена целая секция для его описания.
Модификатор «S»
Этот модификатор позволяет нам проанализировать строку до сопостовления с шаблонами,
которые не помечены якорями. Т.е. если шаблон не имеет начальной фиксированой позиции, как например:
Паттерн может успорить выполение шаблона в случае с множественными совпадениями.
В следующем примере появляется множественное вхождение шаблона, поэтому добавим «S».
// match our pattern containing a special sequence
preg_match_all ( «/[ \w ]/S» , $string , $matches ) ;
// loop through the matches with foreach
foreach ( $matches [ 0 ] as $value ) <
echo $value ;
>
?>
Результат скрипта:
abcefghijklmnopqrstuvwxyz01234567890
На практике модификатор используется достаточно редко.
Модификатор границы слова (word boundary) «\b»
Граница слова создается между двух «\b» модификаторов.
Это специальный «подпирающий тип модификаторов, которые позволяют указть ТОЧНОЕ совпадение.
Текст должен совпасть только с точным шаблоном заключенным в «\b»
Например, шаблон «cat» не совпадет с «catalog».
$string = ‘eregi will not be available in PHP 6’ ;
// ищем строку «lab»
if ( preg_match ( «/ \b lab \b /i» , $string ) ) <
// Совпадение
echo $string ;
> else <
echo ‘Не думаю’ ;
>
?>
Результат скрипта:
Не думаю
Мы пытаемся найти совпадение с паттерном «lab», которое находится внутри строки в слове «available».
Из за использования границ слов, шаблон не совпал с подстрокой.
Давайте попробуем пример, не используя модификатора границ слов.
$string = ‘eregi will remain in the computer lab’ ;
// ищем строку «lab»
if ( preg_match ( «/ \b lab \b /i» , $string ) ) <
// Совпадение
echo $string ;
> else <
echo ‘Не думаю’ ;
>
?>
Результат скрипта:
eregi will remain in the computer lab
Мы видим что совпадение произошло с целым словом «lab». (\blab\b).
Модификатор \B
Этот модификатор относится к предыдущем, но \B не ставит условия гранц слова, а наоборот
отрицает границу слов. Этот модификатор полезен, когда нужно найти что-нибудь внутри
текста, который находится внутри слова, но не в самом начале или конце фразы.
$string = ‘This lathe turns wood.’ ;
// match word boundary and non-word boundary
if ( preg_match ( «/ \B the \b /» , $string ) ) <
echo ‘Совпал шаблон «the».’ ;
> else <
echo ‘Не думаю’ ;
>
?>
Результат скрипта:
>> Совпал шаблон «the».
Этот код сначала найдет паттерн «the». Потому что сначала указан модификатор «не граница слова»,
the находится внутри фразы и не снача ее, затем модификатор \b границы указывает что фраза должна
закончится на -the.
$string = ‘The quick brown fox jumps over the lazy dog.’ ;
// match word boundary and non-word boundary
if ( preg_match ( «/ \B the \b /» , $string ) ) <
echo ‘Совпал шаблон «the».’ ;
> else <
echo ‘Не думаю’ ;
>
?>
Результат скрипта:
Не думаю
В этот раз мы ничего не нашли, потому что «the» стоит на границе слова, а мы использовали модификатор \B.
Последний модификатор — \U
По умолчанию, PCRE «жадный» — это не значит что они съедят вашу печеньку,
а означает что шаблон совпадет с наибольшим возможным количеством символов,
попадающих под этот шаблон.
Чтобы отключить такую «жадность» регулярных выражений
— используем ограничитель «?», например «(.*?)»
— используем модификатор «\U».
Новичкам желательно использовать этот модификатор по-умолчанию, чтобы не возникало конфузов.
$string = ‘foobar foo—bar fubar’ ;
// try to match the pattern
if ( preg_match ( «/foo(.*)bar/U» , $string ) ) <
echo ‘Совпадение’ ;
> else <
echo ‘Не думаю’ ;
>
Результат скрипта:
Совпадение
Другой пример — дан кусок html
Попытаемся найти все ссылки выражением preg_match_all(«/.*/s», $string),
код вернет всю искомую строку вместо трех ссылок. Добавив Нежадный модификатор, все три ссылки поотдельности.
Вычисление с preg_replace
Приветствуем на сцене модификатор «e».
Этот модификатор вычисляет заменяемый аргумент.
До этого мы не рассматривали preg_replace(), поэтому быстрый пример:
$string = ‘We will replace the word foo’ ;
// заменяем `for` на `bar`
$string = preg_replace ( «/foo/» , ‘bar’ , $string ) ;
Пример заменит в строке foo на bar. В таких простых заменах целесообразнее использовать функции обработки строк
str_replace(), которые быстрее справляются с простыми задачами, но имеют некоторые ограничения, например не поддерживают юникод.
// строка с шаблонными переменными
$string = ‘This is the <_FOO_>bought to you by <_BAR_>‘ ;
// создади массив со значениями переменных
$templateVars = [ «FOO» => «The PHP Way» , «BAR» => «PHPro.orG» ] ;
// заменяем и вычисляем
$string = preg_replace ( «/<_(.*?)_>/ime» , » \$ templateVars[‘$1’]» , $string ) ;
Без модификатора «е» скрипты выдаст результат:
This is a $template_vars[FOO] and this is a $template_vars[BAR]
С модификатором переменные вычислятся после замены:
This is the The PHP Way bought to you by PHPro.orG
Таким образом, модификатор «e» обладает потенциалом встроенного шаблонизатора.
Заглядывание вперед (Look Aheads)
Возможность регулярных выражений «заглянуть вперед» шаблона для определения дальнейших совпадений.
«Подглядывание вперед» бывает положительное и отрицательное
Рассмотрим сначала заглядывание вперед с отрицанием. Обозначается в шаблоне символами «?!».
Полезно при поиске шаблона, стоящего впереди от совпадения, которое нам нужно.
$string = ‘I live in the whitehouse’ ;
// try to match white not followed by house
if ( preg_match ( «/white+(?!house)/i» , $string ) ) <
// if we find the word white, not followed by house
echo ‘Совпадение’ ;
> else <
echo ‘Не думаю’ ;
>
?>
Результат скрипта:
No match is found
Потому что слово «white» следует за словом «house».
Подадим блюдо под другим соусом:
$string = ‘I live in the white house’ ;
// try to match white not followed by house
if ( preg_match ( «/white+(?!house)/i» , $string ) ) <
// if we find the word white, not followed by house
echo ‘Совпадение’ ;
> else <
echo ‘Не думаю’ ;
>
?>
Результат скрипта:
Совпадение
Есть совпадение, потому что слово «white» не следует сразу же за словом «house» (как в «whitehouse»)
Позитивное/положительное заглядывание вперед «?=»
$string = ‘This is an example eg: foo’ ;
// try to match eg followed by a colon
if ( preg_match ( «/eg+(?=:)/» , $string , $match ) ) <
print_r ( $match ) ;
> else <
echo ‘Нет совпадений’ ;
>
?>
Результат скрипта:
Array < [0]=>‘eg’ >
Код ищет паттерн «eg», стоящий перед «:» двоеточием.
Но что если нам нужно найти что-то до двоеточия, например дом из предудыщего примера.
Для этого на помощь приходят «заглядывания назад».
Заглядывание назад (Look Behinds)
Позволяет просмотреть строку назад и определить наличие совпадений с шаблоном.
Также разделяется на положительное и отрицательное.
Положительное — записывается «?
$string = ‘I live in the whitehouse’ ;
// try to match house preceded by white
if ( preg_match ( «/(? , $string ) ) <
// if we find the word white, not followed by house
echo ‘Совпадение’ ;
> else <
echo ‘Не думаю’ ;
>
?>
Результат скрипта:
Совпадение
Здесь мы нашли совпадение, потому что паттерн «house» сразу следует за паттерном «house».
Движок регулярных выражений «посмотрел назад» шаблона «house» и определил совпадение.
Если мы хотим, чтобы «house» НЕ следовал за словом «white»?
Используем отрицительное заглядывание назад — «?
/*** a simple string ***/
$string = ‘I live in the whitehouse’ ;
/*** try to match house preceded by white ***/
if ( preg_match ( «/(? , $string ) )
<
/*** if we find the word white, not followed by house ***/
echo ‘Совпадение’ ;
>
else
<
/*** if no match is found ***/
echo ‘Не думаю’ ;
>
?>
Результат скрипта:
no match is found
Потому что отрицательное заглядывание не нашло шаблона «house» c шаблоном «white» в начале его.
Давайте поменяем цвет «дома», белым слишком девственный для правительственного здания.
$string = ‘I live in the bluehouse’ ;
// ищем `house` с непредшествующим `white`
if ( preg_match ( «/(? , $string ) ) <
/*** if we find the word white, not followed by house ***/
echo ‘Совпадение’ ;
> else <
/*** if no match is found ***/
echo ‘Не думаю’ ;
>
?>
Мы изменили «whitehouse» на «bluehouse» и теперь наша регулярка сработала, потому что
шаблон «white» не обнаружен перед «house».
По-умолчанию регулярки жадные, это значит что квантификаторы (какое слово страшное)
*, +, ? «пожирают» столько символов сколько могут.
/*** 4 x and 4 z chars ***/
$string = «xxxxzzzz» ;
/*** greedy regex ***/
preg_match ( «/^(.*)(z+)$/» , $string , $matches ) ;
/*** results ***/
echo $matches [ 1 ] ;
echo «
» ;
echo $matches [ 2 ] ;
?>
Первый паттерн (.*) совпал со всеми четыремя «x» и тремя из четырех символов «z».
Сработала жадность — шаблон забрал столько символов, сколько было в искомой строке.
Проще простого помочь перестать квантификаторам быть жадными, добавив «?» к квантификатору как в примере:
/*** string of characters ***/
$string = «xxxxzzzz» ;
/*** a non greedy match ***/
preg_match ( «/^(.*?)(z+)$/» , $string , $matches ) ;
/*** show the matches ***/
echo $matches [ 1 ] ;
echo «
» ;
echo $matches [ 2 ] ;
?>
Теперь $matches[1] содержит четыре «x» символа и $matches[2] четыре символа «z».
Потому что квантификатор «?» изменил поведение шаблона с «взять как можно БОЛЬШЕ» на «взять как можно МЕНЬШЕ».
Чтобы сделать нежадным весь шаблон, используем модификатор «U».
/*** string of characters ***/
$string = «xxxxzzzz» ;
/*** a non greedy match ***/
preg_match ( «/^(.*)(z+)$/U» , $string , $matches ) ;
/*** show the matches ***/
echo $matches [ 1 ] ;
echo «
» ;
echo $matches [ 2 ] ;
?>
Результат как в предыдущем примере.
Подводные камни c ? и U
Важно заметить, что модификатор «U» не только делает поиск нежадным, он инвертирует поведение жадности квантификатора «?».
Если использовался квантификатор «?» и одновременно модификатор «U», действие «?» будет инвертировано.
/*** string of characters ***/
$string = «xxxxzzzz» ;
/*** a non greedy match ***/
preg_match ( «/^(.*?)(z+)$/U» , $string , $matches ) ;
/*** show the matches ***/
echo $matches [ 1 ] ;
echo «
» ;
echo $matches [ 2 ] ;
?>
Результат скрипта:
xxxxzzz
Delimiters
В этом мане было рассмотрено много регулярок и все они разделялись слэшем «/».
Иногда нам нужно находить в шаблоне слэш и когда он одновременно является разделителем регуляного выражения,
нам придется экранировать каждый встречающийся слэш, что неудобно.
Поэтому в качестве разделителя можно взять любой символ, например #, @, ^ и т.п.
/*** get the host name from a url ***/
preg_match ( ‘#^(?:http://)?([^/]+)#i’ , «http://www.phpro.org/tutorials» , $matches ) ;
/*** show the host name ***/
echo $matches [ 1 ] ;
?>
Примеры
// the string to match against
$string = ‘The cat sat on the mat’ ;
// match the beginning of the string
echo preg_match ( «/^The/» , $string ) ;
// match the end of the string
// returns 1
echo preg_match ( «/mat \z /» , $string ) ;
// match anywhere in the string
// returns 0 as no match was found for dog.
echo preg_match ( «/dog/» , $string ) ;
?>
Поиск нескольких шаблонов
// the string to match against
$string = ‘The cat sat on the matthew’ ;
// matches the letter «a» followed by zero or more «t» characters
echo preg_match ( «/at*/» , $string ) ;
// matches the letter «a» followed by a «t» character that may or may not be present
echo preg_match ( «/at?/» , $string ) ;
// matches the letter «a» followed by one or more «t» characters
echo preg_match ( «/at+/» , $string ) ;
// matches a possible letter «e» followed by one of more «w» characters anchored to the end of the string
echo preg_match ( «/e?w+ \z /» , $string ) ;
// matches the letter «a» followed by exactly two «t» characters
echo preg_match ( «/at<2>/» , $string ) ;
// matches a possible letter «e» followed by exactly two «t» characters
echo preg_match ( «/e?t<2>/» , $string ) ;
// matches a possible letter «a» followed by exactly 2 to 6 «t» chars (att attt atttttt)
echo preg_match ( «/at<2,6>/» , $string ) ;
Запомните, preg_match() возвращает только 0 или 1, и останавливается после первого успешного нахождения шаблона.
Чтобы найти все совпадения — используйте preg_match_all().
Чит Шит
\w — Any “word” character (a-z 0-9 _)
\W — Any non “word” character
\s — Whitespace (space, tab CRLF)
\S — Any non whitepsace character
\d — Digits (0-9)
\D — Any non digit character
. — (Period) – Any character except newline
^ — Start of subject (or line in multiline mode)
$ — End of subject (or line in multiline mode)
[ — Start character class definition
] — End character class definition
| — Alternates, eg (a|b) matches a or b
( — Start subpattern
) — End subpattern
\ — Escape character
n- Zero or more of n
n+ — One or more of n
n? — Zero or one occurrences of n
i — Case Insensitive
m — Multiline mode — ^ and $ match start and end of lines
s — Dotall — . class includes newline
x — Extended– comments and whitespace
e — preg_replace only – enables evaluation of replacement as PHP code
S — Extra analysis of pattern
U — Pattern is ungreedy
u — Pattern is treated as UTF-8
\b — Word boundary
\B — Not a word boundary
\A — Start of subject
\Z — End of subject or newline at end
\z — End of subject
\G — First matching position in subject
(?=) — Positive look ahead assertion foo(?=bar) matches foo when followed by bar
(?!) — Negative look ahead assertion foo(?!bar) matches foo when not followed by bar
(? ) — Once-only subpatterns (?>\d+)bar Performance enhancing when bar not present
(?(x)) — Conditional subpatterns
(?(3)foo|fu)bar — Matches foo if 3rd subpattern has matched, fu if not
(?#) — Comment (?# Pattern does x y or z)
Дополнения от меня
Posix символьные классы
Дополнительные шорткуты для шаблонов. Могут применяться только внутри классов.
Пример для поиска числа с пробелами — preg_match(«@[[:space:]\d][email protected]», $string)
Внутренние модификаторы шаблонов
Модификаторы m, s, x, U, X, J могут использоваться внутри шаблона.
Например (?im) установит мультистроковой регистронезивисимый метод поиска для паттерна.
Отключить внутренние модификаторы можно перечислив их через дефис, например (?im-sx)
Пример:
шаблон (?i:foo) совпадет с «FoO»
Именованный «захват»
Возможность регулярных выражений именовать ключи в результирующем массиве совпадений.
Записывается: (? ), (?’name’) или (?P ).
Раньше поддерживался только такой синтаксис: (?P ). [
preg_match ( ‘/Name: (.+), Age: ( \d +)/’ , $text , $matches ) ;
preg_match ( ‘/Name: (?P .+), Age: (?P \d +)/’ , $text , $matches ) ;
?>
Результат скрипта:
array(‘Name’ => ‘строка’, ‘Age’ => ‘число’)
Замена через callback-функцию
В php есть возможность указать функцию обратного вызова
для совпадений, если нам нужно проделать с ними необычные вещи.
Для этого используется preg_replace_callback.
\s * \w |’ ,
create_function (
‘$matches’ ,
‘return strtoupper($matches[0]);’
) ,
$line
) ;
?>
Данный код заменит все первые буквы в параграфах на заглавные.
В php >= 5.3 callback-функцию можно записать в сокращенном виде
\s * \w |’ ,
function ( $matches ) <
return strtoupper ( $matches [ 0 ] ) ;
> ,
$line
) ;
?>
Website-create.ru
Рано или поздно каждый веб разработчик сталкивается с задачей внедрения в свой код регулярных выражений. Многие думают, что составлять их невероятно сложно и под силу только избранным. На самом деле это не так. И сегодня я покажу Вам как составлять регулярные выражения.
Но для начала немного общей информации. Что такое регулярные выражения и для чего они нужны?
Регуля́рные выраже́ния (англ. regular expressions) — формальный язык поиска и осуществления манипуляций с подстроками в тексте, основанный на использовании метасимволов (символов-джокеров, англ. wildcard characters). По сути это строка-образец (англ. pattern, по-русски её часто называют «шаблоном», «маской»), состоящая из символов и метасимволов и задающая правило поиска.
Выписка из Википедии
Другими словами, регулярное выражени означает регулярную последовательность символов или чисел или какого-нибудь другого шаблона, то есть выражение, которое нужно найти.
Регулярные выражения наиболее часто используются для поиска и подстановки текста, с их помощью можно проверять правильность введенной пользователем информации, дабы избежать ввода некорректной информации или информации в неподходящем формате.
Принцип их работы достаточно прост.
Во-первых, задается строка, в которой будет производиться поиск. Во-вторых, создается шаблон этого самого поиска.
И если Вы знаете как правильно создать шаблон под ту или иную задачу, то при помощи регулярных выражений Вы может найти практически все, что угодно.
Давайте научимся создавать регулярные выражения для php
Будем разбирать сразу все на практике и смотреть на полученные результаты.
Я создаю новый php файл для тестирования всего кода. Вы можете сделать то же самое. Создайте файл и пропишите в нем между тегов body открывающий и закрывающий теги для php кода:
Сразу запустите файл в браузере (убедитесь, что Ваш Денвер работает). Если Вы не знаете, то для запуска файла, нужно прописать в командной строке браузера localhost/имя папки, в которой лежит файл/имя файла.php.
Итак, начнем с самого начала. Для начала я напишу текст, в котором буду икать соответствия и помещу его в переменную (конечно же текст должен быть заключен в кавычки).
Вот такой вот текст. Теперь нужно создать шаблон нашего регулярного выражения.
Давайте пойдем от простого к сложному. Для начала поищем в тексте слово «интернет», узнаем сколько раз оно встречается и выведем на экран.
Для этого давайте составим простой шаблон регулярного выражения и поместим его в переменную.
Начнем с того, что регулярное выражение – это простая строка, и ее нужно взять в кавычки.
Кроме того, регулярные выражения начинаются и заканчиваются с прямого слэша. То, что находится между слешами и составляет суть регулярного выражения.
Таким образом, давайте вставим в наш код самый простейший шаблон регулярного выражения, занесенный в переменную:
Но это всего лишь переменные. А теперь самое главное!
Пропишем функцию, которая будет искать соответствия в нашем тексте по нашему регулярному выражению.
В PHP для этого используется специальная функция «preg_match».
Функция preg_match и функция preg_match_all.
В функцию preg_match передаются 2 параметра: регулярное выражение и строка, в которой нужно вести поиск.
Эта функция может вернуть значения: либо 0 (если совпадения отсутствуют), либо 1 (при обнаружении первого совпадения, а потом просто останавливает поиск).
Если же нам требуются все соответствия с шаблоном, то нужно использовать функцию preg_match_all.
В функцию preg_match_all передаем 3 параметра: регулярное выражение; строка, в которой ведем поиск; переменная, в которую поместим результаты поиска.
Так как нам нужны все совпадения, имеющиеся в тексте, то мы будем использовать функцию preg_match_all. Следовательно, наш код пополнится следующей строкой:
Осталось вывести на экран результат. Я предлагаю сначала вывести число совпадений, а потом и сами эти совпадения в цикле for (возможно на практике вывод результатов Вам и не понадобиться, но в этом уроке я делаю его для наглядности).
Добавим к нашему коду следующие строки:
Теперь если проверить страницу в браузере, то мы увидим следующий результат:
Если нам нужно найти одно значение или другое, например, мы хотим найти слово «интернет» или «сайт», то между искомыми значениями в шаблоне нужно поставить специальный символ «|». В таком случае, регулярное выражение будет выглядеть так:
А результат на экране мы увидем такой:
Но это все очень просто. Давайте займемся чем-то посложнее, например найдем все адреса сайтов, прописанных в нашем тексте. Обратите внимание, что они прописаны в разных форматах (одни с www, другие с http:// и даже с http://www.. Одни заканчиваются на .ru, другие на .com). Согласитесь, это уже интереснее! Давайте начнем.
Предлагаю начать с конца.
1. Для начала давайте скажем нашему шаблону вывести все с .ru или с .com.
Сделаю небольшое отступление и скажу, что точка (.) в регулярных выражениях обозначает – «любой символ», поэтому точку нужно экранировать. Сделать мы это можем при помощи обратного слэша (\). С символом или (|) Вы уже знакомы.
Пока получается вот так:
И действительно, шаблон найдет нам все, что заканчивается на эти символы. Помимо адресов веб сайтов он также учтет и адреса электронной почты, так как они тоже заканчиваются на эти символы. Но далее мы это исправим.
2. Теперь укажем, что перед .ru или .com могут стоять символы латинского алфавита от a до z, также цифры от 0 до 9 и знак «-». Это будет выглядеть так: [a-z0-9-]. А еще нам нужно указать квантор (простыми словами: то, сколько таких символов может быть). Например, если я напишу так: <2,>– это будет значить 2 или больше.
Осталось все это объединить. Кстати перед этим нужно заключить уже имеющуюся часть (\.ru)|(\.com) в скобки. Если мы этого не сделаем, то все, что мы намишем впереди будет относиться только к .ru.
Объединяя все вышесказанное, получим такой код:
А на экране увидем следующее:
Уже лучше, но шаблон по-прежнему выдает нам также и адреса электронной почты. Сейчас мы это исправим.
3. Теперь нам нужно выбирать только те совпадения, которые будут начинаться либо с www., либо с http://. Так мы исключим из нашего списка выдачу адресов электронной почты, которые туда попали.
Что для этого нужно сделать?
Следующая часть выражения будет стоять в самом начале (помните, мы идем от конца к началу), ее мы заключим в скобки. Далее в скобках пропишем, что нас интересует http:// (слэши здесь тоже нужно экранировать) или (|) www. (точку тоже нужно экранировать). После скобок откроем фигурные скобки и пропишем квантор ( <1>– значит это выражение должно встречаться ровно один раз). Получается вот такой код:
Теперь, если обновить страничку в браузере, то мы увидем, что в результате нам показываются только адреса веб сайтов, как и было задумано:
Теперь, я думаю, что Вам стало понятно, как составить такое регулярное выражение. Оно, конечно же не универсально, я просто придумала его для примера. Уверена, что если посидеть и хорошенько подумать, то можно его усовершенствовать.
Вообще, составление регулярного выражения похоже на составление уровнения.
Давайте рассмотрим еще один простой пример.
Найдем все упоминания годов в нашем тексте.
Сделать это необычайно просто.
Год должен состоять из цифр. Для этого мы будем использовать символьный класс (\d). Этот символьный класс обозначает – «Цифра». Кроме того, год должен состоять из четырех цифр, а для этого мы будем использовать квантор <4>.
В итоге, регулярное выражение будет выглядеть вот так:
А в результате мы получим вывод всех годов, встречающихся в тексте (у нас их в тексте два):
На последок я хочу Вам предложить один очень неплохой ресурс, который поможет Вам в изучении регулярных выражений. Называется он regexlib.com .
В нем есть тестер регулярных выражений. То есть вы можете писать регулярные выражения и тестировать их работу прямо в этом ресурсе. Для этого нужно перейти на вкладку «Redex Tester», в поле «Source» нужно прописать тот текст, в котором будет производиться поиск. А в поле «Regular Expression» нужно писать само регулярное выражение. Обратите внимание, что когда будете писать регулярное выражение, то вводить “//” в поле не нужно. Сразу пишите само регулярное выражение. После написания нажимаете на кнопку «Submit» и смотрите результаты. Это очень удобно!
Кроме того, на сервисе Вы можете найти примеры регулярных выражений. Для этого нужно перейти на вкладку «Browse Expressions» и Вы увидите синенькие кнопочки, обозначающие категории регулярных выражений для разных задач. Вы можете воспользоваться готовыми решениями для Ваших веб проектов, а также (если Вам действительно хочется научиться их составлять самому) поразбираться в них.
На самом деле о регулярных выражениях можно писать очень много, но хочется сказать, что чтобы научиться писать их быстро и эффективно нужно практиковаться. Практикуйтесь! Ведь так приятно, когда запускаешь скрипт, а он работает как надо!
Подписывайтесь на обновление блога, обещаю Вам много всего интересного! А также жду Ваших комментариев, вопросов и предложений.
Регулярные выражения (урок PHP)
Историю появления и развития регулярных выражений в PHP — смотрите в видеоуроке Андрея Кудлая.
«Вы познакомитесь с понятием «регулярные выражения», узнаете историю их появления и развития, получите представление об источниках получения информации по этой непростой теме, а также получите необходимый инструментарий, облегчающий создание и тестирование шаблонов.» © Андрей Кудлай
Ваши ссылки: скачать видео
Информация о видео
Источник: уроки по созданию сайта.
Автор видео: Андрей Кудлай — родом из Украины, живет в Днепропетровске. Веб-программированию учился сам. Неплохо знает HTML, CSS, PHP, JavaScript..
Формат видео: *.mp4.
Продолжительность: 00:37:16
Размер архива: 190 MБ.
Дополнительно: исходные материалы добавлены в архив с видео.
Нравится информация? Расскажите о ней в своей социальной сети!
Вам также может понравиться
FAQ на сайте с использованием PHP, jQuery и текстовых файлов — 3 часть (видеоурок)
Контроллеры и виды (урок Yii2)
Получаем максимальное значение (урок MySQL)
ЧПУ адреса (урок Yii2)
FAQ на сайте с использованием PHP, jQuery и текстовых файлов — 2 часть (видеоурок)
FAQ на сайте с использованием PHP, jQuery и текстовых файлов — 1 часть (видеоурок)
Оставить комментарий X
Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.
- видеоуроков и видеокурсов;
- семинаров и тренингов;
- интенсивов;
- записей вебинаров;
- скринкастов.
и другого обучающего видео.
Навигация по архиву
Ещё интересное видео
Установка DataLife Engine (урок DLE)
Как установить CMS DLE (DataLife Engine) на сервер — смотрите в видеоуроке Андрея Кудлая. «В данном уроке мы установим движок на сервер.» © Андрей Кудлай Информация о видео Источник: уроки по созданию сайта. Автор видео: Андрей Кудлай — родом из Украины, живет в Днепропетровске. Веб-программированию учился сам. Неплохо знает HTML, CSS, PHP, JavaScript.. Формат видео: […]
Перенос сайта на хостинг (урок WordPress)
Как сайт работающий под управлением CMS WordPress перенести на хостинг — смотрите в видеоуроке Андрея Кудлая. «В этом уроке мы расскажем о переносе сайта WordPress на хостинг с локального компьютера (или другого хостинга)» © Андрей Кудлай Информация о видео Источник: уроки по созданию сайта. Автор видео: Андрей Кудлай — родом из Украины, живет в Днепропетровске. […]
Регулярные выражения
Функции сравнения строк и поиска подстрок, рассмотренные в предыдущей статье, позволяют успешно справляться с теми задачами, для которых они предназначены, но имеют существенные ограничения в том, что основаны на использовании литеральных значений. В качестве иллюстрации того, в чем состоят ограничения этих функций, рассмотрим следующий пример. Предположим, требуется выполнить проверку строк для определения того, относятся ли эти строки к конкретному типу имени хоста веб-сайта. Адреса, представленные этим именем, должны начинаться с подстроки www., оканчиваться подстрокой .com и иметь в середине одно слово, состоящее из прописных букв. В качестве примера ниже приведены строки, имеющие требуемый формат:
А эти строки не соответствуют указанным требованиям:
Даже краткие размышления показывают, что в нашем распоряжении пока что нет удобного способа, позволяющего воспользоваться средствами сравнения строк и подстрок для проведения требуемой проверки. Мы можем проверить наличие подстрок www. и .com, но гораздо сложнее проверить соответствие заданным требованиям той подстроки, которая находится между ними. Однако с этой задачей позволяют легко справиться регулярные выражения.
Для сокращенного обозначения регулярных выражений в английском языке применяется термин . Регулярные выражения представляют собой шаблоны для согласования со строками, содержащие специальные подстановочные символы, которые могут быть согласованы с целыми фрагментами целевой строки. Язык PHP позволяет применять два широких класса регулярных выражений: регулярные выражения, совместимые со стандартом POSIX (называемые расширенными), и обычные регулярные выражения, совместимые с языком Perl. Различия между этими классами в основном касаются синтаксиса, но имеются также некоторые функциональные различия.
В конечном итоге регулярные выражения в стиле POSIX явились итогом развития средств сопоставления с шаблонами регулярных выражений, используемых в интерпретаторах Unix с интерфейсом командной строки, а регулярные выражения, совместимые с языком Perl, в большей степени напоминают соответствующие средства указанного языка. Любой разработчик, которому предстоит выполнить хоть сколько-нибудь существенный объем программирования в среде веб, рано или поздно будет вынужден воспользоваться регулярными выражениями.
Начиная с версии PHP 5.3.0 функции для работы с регулярными выражениями в стиле POSIX являются устаревшими, поэтому далее мы будем рассматривать регулярные выражения в стиле Perl.
Регулярные выражения, совместимые с языком Perl
Для обработки регулярных выражений, совместимых с языком Perl, в языке PHP применяется полностью отдельный набор функций, а формирование шаблонов осуществляется следующим образом:
Шаблоны регулярных выражений, совместимых с языком Perl, всегда начинаются и оканчиваются одним конкретным символом, который должен быть одинаковым и в начале и в конце. Этот символ отмечает начало и конец шаблона. В соответствии с общепринятым соглашением для этой цели чаще всего используется символ /, но при желании может также применяться другой символ. Следующий шаблон, совместимый с языком Perl: /pattern/, согласуется с любой строкой, которая содержит в себе строку (вернее, подстроку) «pattern».
Сопоставление символов с такими же символами, которые не являются специальными, осуществляется непосредственно. Например, буква в шаблоне согласуется с той же буквой в целевой строке.
Специальный символ ^ согласуется только с началом строки, а специальный символ $ — только с концом строки.
Специальный символ . согласуется с любым символом.
Специальный символ * обеспечивает согласование заданного перед ним регулярного выражения в количестве от нуля или больше, а символ + указывает, что согласование достигается, если количество обнаруженных в целевой строке экземпляров стоящего перед ним регулярного выражения составляет от одного и больше.
Набор символов, заключенный в квадратные скобки, согласуется с любым из символов этого набора. Например, шаблон [ab] согласуется и с буквой a, и с буквой b. В квадратных скобках можно также определить диапазон символов с использованием дефиса. Например, шаблон [a-c] согласуется с буквой a, b или c.
Специальные символы, отмеченные знаком переключения режима обработки в виде обратной косой черты (\), теряют свое специальное значение и сопоставляются непосредственно, как обычные символы.
Если рассматриваемый символ не является специальным, то шаблон в стиле Perl последовательно согласует символы. Например, шаблон /abc/ согласуется с любой строкой, которая содержит подстроку «abc»
Любой шаблон, за которым следует символ ? (вопросительный знак), означает: «Выполнить согласование конструкции, предшествующей этому символу, нуль или один раз».
Любой символ, который имеет в регулярном выражении специальное значение, может быть преобразован в простой, буквально согласуемый символ путем введения перед ним префикса в виде обратной косой черты (знак переключения на другой режим обработки). Специальные символы, которые требуют применения знака переключения, чтобы можно было выполнять согласование с их буквальными значениями, перечислены ниже.
Круглые скобки, выделяющие любую часть шаблона, означают: «Добавить подстроку, которая согласуется с этим подвыражением, к списку подстрок, согласованных с шаблоном»
Рассмотрим в качестве примера следующий шаблон:
Он согласуется с любой строкой, содержащей литеральное выражение «тел.», за которым следует какое-то количество пробелов (но не меньше одного), после чего приведено точно семь цифр (без пробелов и дефисов). Кроме того, в этом шаблоне заданы круглые скобки, поэтому номер, состоящий из семи цифр, сохраняется и возвращается в виде массива, содержащего подстроки сопоставления, если данный шаблон вызывается из функции, которая возвращает подобные объекты.
В следующей таблице представлены все данные по использованию специальных символов в регулярных выражениях:
Классы символов | |
---|---|
[. ] | Любой из символов, указанных в скобках |
[^. ] | Любой из символов, не указанных в скобках |
. | Любой символ, кроме перевода строки или другого разделителя Unicode-строки |
\w | Любой символ, образующий «слово» |
\W | Любой символ, не являющийся текстовым символом |
\s | Любой пробельный символ из набора Unicode |
\S | Любой непробельный символ из набора Unicode. Обратите внимание, что символы \w и \S — это не одно и то же |
\d | Любые ASCII-цифры. Эквивалентно [0-9] |
\D | Любой символ, отличный от ASCII-цифр. Эквивалентно [^0-9] |
Символы повторения | |
Соответствует предшествующему шаблону, повторенному не менее n и не более m раз | |
Соответствует предшествующему шаблону, повторенному n или более раз | |
Соответствует в точности n экземплярам предшествующего шаблона | |
? | Соответствует нулю или одному экземпляру предшествующего шаблона; предшествующий шаблон является необязательным. Эквивалентно |
+ | Соответствует одному или более экземплярам предшествующего шаблона. Эквивалентно |
* | Соответствует нулю или более экземплярам предшествующего шаблона. Эквивалентно |
Символы регулярных выражений выбора | |
| | Соответствует либо подвыражению слева, либо подвыражению справа (аналог логической операции ИЛИ). |
(. ) | Группировка. Группирует элементы в единое целое, которое может использоваться с символами *, +, ?, | и т.п. Также запоминает символы, соответствующие этой группе для использования в последующих ссылках. |
(. ) | Только группировка. Группирует элементы в единое целое, но не запоминает символы, соответствующие этой группе. |
Якорные символы регулярных выражений | |
^ | Соответствует началу строкового выражения или началу строки при многострочном поиске. |
$ | Соответствует концу строкового выражения или концу строки при многострочном поиске. |
\b | Соответствует границе слова, т.е. соответствует позиции между символом \w и символом \W или между символом \w и началом или концом строки. |
\B | Соответствует позиции, не являющейся границей слов. |
(?=p) | Позитивная опережающая проверка на последующие символы. Требует, чтобы последующие символы соответствовали шаблону p, но не включает эти символы в найденную строку. |
(?!p) | Негативная опережающая проверка на последующие символы. Требует, чтобы следующие символы не соответствовали шаблону p. |
\A | начало данных (независимо от многострочного режима) |
\Z | конец данных либо позиция перед последним переводом строки (независимо от многострочного режима) |
Флаги (указываются в конце рег. выражения) | |
i | Указывает, что поиск по шаблону должен быть нечувствителен к регистру символов. |
m | Многострочный режим поиска (multiline). |
s | Если данный модификатор используется, метасимвол «точка» в шаблоне соответствует всем символам, включая перевод строк. |
x | Если используется данный модификатор, неэкранированные пробелы, символы табуляции и пустой строки будут проигнорированы в шаблоне, если они не являются частью символьного класса. |
Общие сведения о функциях, совместимых с языком Perl, приведены в таблице ниже:
Функция | Описание |
---|---|
preg_match() | |
preg_match_all() | |
preg_split() | |
preg_replace() | Принимает в качестве параметров шаблон, строку замены и строку, в которой должны быть внесены изменения. Возвращает модифицированную строку, в которой вместо каждой подстроки, согласованной с шаблоном, подставлена строка замены. Необязательный параметр с обозначением предельного количества определяет, сколько должно быть выполнено замен (как в функции preg_split()) |
preg_replace_callback() | Эта функция аналогична функции preg_repiace(), за исключением того, что вторым параметром является имя функции обратного вызова, а не строка замены. Эта функция должна возвращать строки, предназначенные для использования в качестве замены |
preg_grep() | Принимает в качестве параметров шаблон и массив и возвращает массив, состоящий из элементов входного массива, который сопоставляется с шаблоном. Значения, перешедшие из старого массива в новый массив, имеют такие же ключи, как и соответствующие элементы исходного массива |
preg_quote() | Функция специального назначения, предназначенная для вставки знаков переключения на другой режим обработки в строки, которые предназначены для использования в качестве шаблонов регулярных выражений. Для этой функции требуется единственный параметр—строка, в которую должны быть вставлены знаки переключения; возвращаемым значением является та же строка, в которой перед каждым специальным символом регулярного выражения вставлена обратная косая черта (знак переключения) |
По-видимому, наиболее широко используемыми из этих функций являются preg_match() и preg_match_all(). Первая функция представляет собой наилучшее средство получения ответа на простой вопрос о том, сопоставляется ли некоторый шаблон с некоторой строкой, а последняя функция является удобным средством подсчета количества согласований или получения сразу всех согласующихся подстрок.
Необязательный четвертый параметр функции preg_match_all() требует дополнительных пояснений. Как правило, массив, который содержит возвращаемые результаты согласования, имеет двухуровневую структуру. На первом уровне показана очередность сопоставлений (первое сопоставление, второе и т.д.), а на втором показана позиция сопоставления в шаблоне. (Все сопоставление всегда находится на первом месте, а за ним следуют по порядку все субшаблоны, обозначенные круглыми скобками.) Вопрос заключается в следующем: «Какой уровень является самым верхним? Будет ли возвращаемый массив представлять собой список элементов с указанием позиций, каждый из которых содержит список номеров последовательных согласований, или данный массив имеет обратную структуру?»
Если четвертым параметром является PREG_PATTERN_ORDER, то первый элемент содержит данные обо всех сопоставлениях с субшаблонами во всем шаблоне, второй элемент содержит данные обо всех сопоставлениях с первым субшаблоном, заключенным в круглые скобки, и т.д. Если же в качестве четвертого параметра применяется флажок PREG_SET_ORDER, то первый элемент представляет собой список всех подстрок из первого сопоставления (в этом списке в начале представлены общие результаты сопоставления, а затем последовательно приведены результаты сопоставления с субшаблонами, заключенными в круглые скобки), второй элемент содержит все подстроки из второго сопоставления и так далее (в следующем разделе приведен пример, который может служить иллюстрацией к этому описанию).
Давайте рассмотрим сначала простой пример, в котором извлекаются все телефонные номера из подстроки и выбирается код страны, код города и номер:
Код PHP «; // Шаблон регулярного выражения $pattern = ‘/(\d+)[\s|\(|-]*([\d]<3,>)[\s|\)|-]*([\d|-]+)/’; preg_match_all($pattern, $str, $arr, PREG_SET_ORDER); foreach ($arr as $entry) < echo "
Этот код даст следующий результат:
Использование регулярных выражений для поиска телефонных номеров
Я могу долго объяснять принцип работы представленного в примере регулярного выражения, но я лучше покажу:
Схема использования регулярного выражения
Пример: программа извлечения ссылок
В качестве более сложного примера того, какие действия могут быть выполнены с помощью регулярных выражений, рассмотрим функцию, позволяющую извлекать ссылки из текста произвольной веб-страницы и выводить полученные результаты на экран. Входными данными служит URL страницы, которая должна быть проанализирована, а выходными данными являются выведенный на экран список ссылок, представленных на соответствующей странице. Этот список состоит из целевого URL для данной ссылки и описательного текста, присутствующего в этой ссылке (который принято называть анкором (или якорем ссылки)). Для решения указанной задачи используются функции для работы с регулярными выражениями, совместимыми с языком Perl.
Разработка такой функции может стать самым первым шагом при создании веб-навигатора для поисковой машины. Поисковики (Google, Yandex и т.п.) загружают содержимое веб-страниц для их анализа и индексации. В ходе работы возникает необходимость распознавать ссылки на другие страницы, если новое информационное наполнение можно будет найти только на этих страницах.
Основное регулярное выражение
Основой разрабатываемой небольшой функции должно служить само регулярное выражение. Необходимо прежде всего разработать такое регулярное выражение, которое сопоставляется только со ссылками HTML (и ничем иным) и может применяться для извлечения фрагментов таких ссылок. Ссылки HTML, как правило, выглядят таким образом:
Это означает, что ссылка задана дескриптором анкора, который имеет атрибут href, а между начальным дескриптором () и конечным дескриптором () заключен текст анкора. В данном разделе будет создан шаблон, предназначенный для сопоставления со ссылкой такого упрощенного типа. (Разрабатываемый шаблон не позволяет обрабатывать все данные, которые согласно спецификации языка HTML разрешено использовать в качестве допустимых анкорных ссылок. В частности, в анкорах разрешены и другие атрибуты, кроме href, но при решении рассматриваемой задачи такая возможность игнорируется.)
Прежде всего необходимо отметить, что регулярные выражения, рассматриваемые как единое целое, считаются весьма трудными для восприятия (в этом вы могли убедиться на примере выше). Поэтому регулярное выражение, предназначенное для решения данной задачи, будет создаваться на основе нескольких черновых вариантов, описание которых приведено по ходу изложения.
Вначале рассмотрим самое несложное выражение, которое предназначено для поиска начала дескриптора анкора. Первый черновой вариант может выглядеть следующим образом:
Обратите внимание на то, что разрабатываемый шаблон еще не предназначен для использования в работоспособном коде PHP; в данном случае создается черновой вариант выражения, которое должно быть вставлено в код PHP позднее. На обычном языке первое черновое определение дескриптора анкора можно описать как состоящее из левой угловой скобки, за которой следует буква «a», затем — пробел, вслед за ним — строка «href=», знак двойной кавычки, произвольное количество символов, отличных от знаков кавычки, заключительный знак кавычки и, наконец, правая угловая скоба. После его составления все выражение заключается в пару символов косой черты, которые служат для машины обработки регулярных выражений указанием на то, где начинается и оканчивается выражение.
Конструкция [^»]+ в середине этого выражения означает примерно следующее: квадратные скобки указывают применяемый набор символов, а знак вставки (^), который непосредственно следует за левой скобкой, указывает, что используется отрицание этого множества символов. Таковым является множество, содержащее все символы, не находящиеся в последующем списке. Наконец, знак + после обозначения класса символов, заключенного в квадратные скобки, показывает, что подразумевается наличие в шаблоне по меньшей мере одного символа, отличного от кавычки.
Как уже было сказано, мы не ставили перед собой задачу точно отразить синтаксис, предписанный спецификацией HTML. Однако существует целый ряд способов, с помощью которых можно немного ослабить ограничения, налагаемые этим выражением. Прежде всего, насколько известно, количество пробелов между начальным символом Код PHP
В качестве текста анкора допускается использовать любой текст, который занимает на странице место вплоть до заключительного дескриптора анкора, поэтому создается класс символов, который включает любые символы, кроме правой угловой скобой ([^>]*), и указывает, что данные символы могут присутствовать в количестве от нуля и больше. Наконец, вводится субшаблон для сопоставления с закрывающим дескриптором анкора ( ).
Применение данного шаблона вполне обеспечивает обработку дескрипторов анкора в том виде, который используется в качестве исходного определения, но обеспечивает сопоставление только с такими анкорами, в которых имя дескриптора (а) и атрибут (href) заданы строчными буквами. Однако допускается с тем же успехом использовать дескрипторы с прописными буквами, поэтому добавим модификатор i после всего выражения, чтобы указать на режим сопоставления без учета регистра:
Этот черновой вариант является почти полностью законченным и может использоваться для получения положительного или отрицательного ответа на вопрос о том, содержит ли страница ссылки такого типа, который нам требуется. Но мы обязаны провести дополнительную работу и извлечь определенные фрагменты любой строки, сопоставляемой с шаблоном. Для указания на это вводятся круглые скобки, заключающие в себе те подстроки, которые нас интересуют (в этом выражении добавлен модификатор x, чтобы экранировать пробелы в рег. выражении, которые вводятся для его удобочитаемости):
Разрабатываемый шаблон к этому времени уже стал намного более сложным для восприятия, но суть изменения состоит в том, что введена пара круглых скобок, которые заключают в себе целевое значение атрибута href (находящееся между кавычками) и еще одну пару вокруг области текста анкора (между дескрипторами). Эти круглые скобки служат для вызывающей функции указанием на то, что необходимо сохранить части строки, сопоставляемые с подвыражениями, заключенными в круглые скобки, чтобы соответствующие подстроки могли быть введены в возвращаемый массив.
Использование данного выражения в функции
После получения необходимого выражения для сопоставления с дескриптором анкора можно приступить к решению следующей задачи — написанию функции, извлекающей ссылки с HTML-страницы. Для этого необходимо осуществить описанные ниже действия:
Принять в качестве параметра заданный URL.
Открыть соединение HTTP с помощью указанного URL и получить информационное наполнение страницы в виде строки.
Выполнить обработку строки в цикле, применяя рассматриваемый шаблон регулярного выражения и сохраняя результаты согласования.
Вывести на экран все пары извлеченных подстрок (состоящие из целевого URL и текста анкора).
В примере ниже показана полная структура целевой страницы включая функцию print_links():
Простая программа поиска ссылок на PHP
Задача разработки этой функции проще, чем кажется на первый взгляд, поскольку в языке PHP уже предусмотрены многие ее составляющие. В частности, не требуется предусматривать каких-либо особых действий по созданию соединения HTTP для загрузки веб-страницы, поскольку функция fopen() принимает URL в качестве параметра и выполняет все необходимое. Поэтому достаточно после вызова функции fopen() с указанным в ней URL считывать символы до тех пор, пока поступление этих символов не прекратится, добавляя полученные данные к создаваемой строке.
Обработка в цикле содержимого HTML-страницы обеспечивается с помощью функции preg_match_all(). В этой функции шаблон регулярного выражения применяется максимально возможное количество раз, после каждого использования обработка строки начинается непосредственно вслед за тем участком, где перед этим было обнаружено совпадение с шаблоном, и результаты поиска сохраняются в массиве $match_array. Здесь мы решили применить структуру массива, упорядоченную в соответствии с флажком PREG_SET_ORDER. Это означает, что каждая запись в массиве верхнего уровня представляет собой часть, соответствующую результатам конкретного согласования с шаблоном в текущей итерации, а не часть, полученную в результате всех согласований.
SG-Team™
Cайт работает по безопасному протоколу https. Сертификат выдан AO Kaspersky Lab
Регулярные выражения на PHP — это невероятно мощное средство для работы с текстами, для поиска по массиву текста, проверки и обработки текста, и многое другое.
В нашем видеокурсе по регулярным выражениям на PHP, вы ознакомитесь со многими примерами и сами сможете создавать свои шаблоны. При помощи шаблонов регулярных выражений можно найти в тексте буквально что-угодно. Именно благодаря мощи регулярных выражений, они включены во многие языки программирования — PERL, PHP, javascript, Python, Ruby и множество других. Поддержка регулярных выражений включена во множество редакторов — Notepad++, Sublime Text, AkelPad, все возможные IDE. Несмотря на все преимущества использования регулярных выражений, многие веб-мастера сами отмечают, что паттерны (шаблоны) регулярных выражений являются их слабым местом. Для новичков шаблоны вообще представляют собой китайскую грамоту. Именно по этим соображениям мы рекомендуем Вам курс по регулярным выражениям на PHP. Благодаря урокам предлагаемого курса Вы на простых и понятных примерах изучите такую относительно сложную тему, как регулярные выражения.
Информация о видеокурсе
Название: Курс по регулярным выражениям на PHP
Автор: Андрей Кудлай
Год выхода: 2015
Жанр: Видеокурс
Язык: Русский
Содержание:
Урок 01. Введение и общие понятия
Урок 02. Метасимволы и модификаторы шаблона
Урок 03. Символьные классы
Урок 04. Работа с пробельными символами
Урок 05. Метасимволы символьных классов
Урок 06. Квантификаторы
Урок 07. Интервальные квантификаторы
Урок 08. Жадные и ленивые квантификаторы
Урок 09. Метасимволы начала и конца строки
Урок 10. Метасимволы границы и не границы слова
Урок 11. Подвыражения в шаблоне
Урок 12. Обратные ссылки
Урок 13. Операция замены в регулярных выражениях
Урок 14. Просмотр вперед и назад
Урок 15. Функции PHP для работы с регулярными выражениями
Урок 16. Функции PHP для работы с регулярными выражениями. Часть 2
Урок 17. Режим юникода в регулярных выражениях
Урок 18. Свойства юникода
Урок 19. Именованные подвыражения
Урок 20. Практика работы с регулярными выражениями
Выпущено: Украина
Продолжительность: 12:35:50
103 Kbps
Аудио: AAC, 125 Kbps, 48.0 KHz
Размер файла: 1.16 Gb
Навигация
« Ноябрь 2020 » | ||||||
---|---|---|---|---|---|---|
Пн | Вт | Ср | Чт | Пт | Сб | Вс |
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 |
Новости
Трамп вывел войска из Сирии, потому что США проиграли там кампанию — Ищенко
Более того, подчеркнул эксперт, США и дальше будут выводить войска из Сирии, поскольку проиграли кампанию в этом регионе, не сумев убрать руководство страны во главе с Башаром Асадом. «Для всех .
Трамп отказался отменить все пошлины на продукцию из КНР
Президент США Дональд Трамп против отмены всех американских таможенных пошлин на китайскую продукцию. Об этом лидер Соединенных Штатов заявил в пятницу во время беседы с журналистами на Южной лужайке .
Партнеры Джулиани требовали от Порошенко расследования против Байдена
Партнеры адвоката Дональда Трампа Руди Джулиани просили экс-президента Украины Петра Порошенко открыть расследование в отношении Хантера Байдена, сообщает The Wall Street Journal/
Зеленский перечислил изобретения украинцев
Президент Украины Владимир Зеленский заявил, что его соотечественники создали первый вертолет, ракетный двигатель, искусственный спутник Земли и целый ряд других изобретений. Об этом он заявил в ходе .
WSJ: партнеры Джулиани добивались от Порошенко начала расследования против Байдена
НЬЮ-ЙОРК, 9 ноября. /ТАСС/. Предполагаемые партнеры Рудольфа Джулиани — адвоката президента США Дональда Трампа — предлагали бывшему президенту Украины Петру Порошенко начать расследование .
Трамп назвал заявления о вмешательстве РФ в выборы самой большой ложью
Утверждения о якобы российском вмешательстве в выборы 2020 года и о связях президента США Дональда Трампа с Россией являются самой большой ложью. Об этом в пятницу заявил глава Белого дома, выступая .
Помпео назвал стабильность на Украине проектом США
Госсекретарь США Майк Помпео заявил, что американская сторона крайне заинтересована в достижении стабильности на Украине, передает РИА «Новости». Помпео подчеркнул, что «это проект», над которым .
Усатый нянь: кот спас ребенка и стал героем Сети
Несмотря на бдительность, питомец очень аккуратно оттолкнул ребенка от лестницы, преградив при этом собой путь и предотвратив беду. Домашний кот спас маленького от ребенка от падения с лестницы. .
Помпео: призыв ООН прекратить блокаду Кубы «ранит народ» этой страны
ВАШИНГТОН, 9 ноя — РИА Новости. Госсекретарь США Майк Помпео выразил сожаление в связи с призывом ООН прекратить экономическую блокаду Кубы, который, по его словам, «ранит гордый народ» этой .
Помпео обсудил с вице-канцлером Германии помощь Украине
ВАШИНГТОН, 9 ноя — РИА Новости. Госсекретарь США Майк Помпео в Берлине провел встречу с вице-канцлером Германии и министром финансов Олафом Шольцем и обсудил торговлю, телекоммуникации, НАТО .
Помпео назвал достижение стабильности на Украине проектом США
Госсекретарь Майк Помпео в ходе пресс-конференции в Берлине заявил, что США крайне заинтересованы и активно содействуют достижению мира и стабильности на Украине. «Это проект, над которым .
Помпео обсудил с Меркель противодействие глобальным вызовам
ВАШИНГТОН, 9 ноября. /ТАСС/. Госсекретарь США Майкл Помпео обсудил в Берлине с канцлером ФРГ Ангелой Меркель сотрудничество в противодействии глобальным вызовам. Об этом говорится в распространенном .
Стало известно о новой причине расторжения ДРСМД
Вашингтон сообщил, что причиной расторжения Договора о ликвидации ракет средней и меньшей дальности (ДРСМД) стала не крылатая ракета 9М729 комплекса «Искандер-М», а некое другое оружие. Об этом .
В США рассчитывают на подписание первой части сделки с КНР в декабре
США рассчитывают подписать соглашение по итогам первого этапа переговоров по торговой сделке с Китаем до конца 2020 года, заявил в эфире CNBC глава аппарата вице-президента США Марк .
Moody’s ухудшило прогноз по рейтингу Великобритании до негативного
В последний раз Moody’s пересматривало суверенный рейтинг Соединенного Королевства в сентябре 2020 года: тогда показатель был понижен на одну ступень в ожидании Brexit. Международное рейтинговое .
Facebook удалит все упоминания осведомителя, пожаловавшегося на Трампа
МОСКВА, 9 ноя — РИА Новости. Компания Facebook заявила, что удалит из соцсети все упоминания предполагаемого имени осведомителя, который подал жалобу на президента США Дональда Трампа из-за разговора .
Украинский экс-министр предрек развал страны
Украина медленно, но уверенно идет по пути распада государства на мелкие части по примеру Югославии. Такое мнение в эфире телеканала NewsOne высказал экс-депутат Верховной рады, бывший министр .
Трамп рассказал о неизвестном разговоре с Зеленским
Президент США Дональд Трамп заявил, что у него была еще одна беседа с украинским коллегой Владимиром Зеленским, о которой никто не знает. Его слова передает CNBC. По словам американского лидера, этот .
Политолог объяснил, почему США признали НАТО устаревшей
Политологи прокомментировали заявление госсекретаря США Майкла Помпео об устаревании НАТО. Такой риск, считает госсекретарь, у трансатлантического альянса есть всегда, но этого можно избежать, если .
ЛНР напомнила Киеву условия разведения сил в Донбассе
Отсутствие вооруженных людей на участках разведения сил и средств в Донбассе является одним из условий отвода сил в Донбассе, говорится в заявлении руководителя представительства ЛНР в Совместном .
Регулярные выражения для продвинутых пользователей
Регулярные выражения это словно “Швейцарский армейский нож” который разрезает блоки информации по определённым шаблонам. Они сопровождаются огромным арсеналом инструментов, о существовании некоторых не знают даже те, кто не раз писал регулярки. Сегодня мы рассмотрим некоторые продвинутые техники, которые вы сможете применить в ваших проектах.
Добавляем комментарии
Иногда (100% преувеличение 🙂 ) регулярные выражения сложны или вовсе непонятны. Написав какое-то выражение сегодня, завтра вам возможно понадобится несколько попыток, чтобы вспомнить как функционирует тот или иной шаблон. Как и во всех случаях жизни (что касается программирования) не забывайте писать комментарии к своим регулярным выражениям.
К примеру вот пример выражения для проверки телефонного номера в США:
Благодаря комментариям этот код становится намного понятнее:
Давайте пустим этот код в привычную для него среду:
Хитрость заключается в символе “\x” в конце выражения. Это позволяет игнорировать пробелы (исключение: экранированные пробелы при помощи \s) в самом выражении для того, чтобы мы могли использовать комментарии (начинающиеся с # и заканчивающиеся перед переходом на новую строку);
Использование функций обратного вызова
В PHP существует функция preg_replace_callback(), которая используется для добавления функций обратного вызова к регулярным выражениям.
Иногда возникает задача, когда нужно произвести нескольких замен в тексте. Если использовать функции preg_replace() или str_replace() для каждого шаблона, строка будет обрабатываться несколько раз.
Давайте рассмотрим пример с шаблоном email:
Заметим, что любой из “маркеров”, представленных в вырежении выше, заключён в квадратные скобки. Мы можем выследить их с помощью регулярки и заменить при помощи функции обратного вызова.
Вот так мы и поступим:
Теперь строка используется только единожды.
“Сетка” против “Не сетки”
Перед тем, как объясниться, я продемонстрирую пример. Предположим, что нам необходимо найти угловые скобки html элементов:
Давайте добавим второй тег:
Всё это работает благодаря тому, что ссылки находятся на разных строках. Если поместить их на одной, данный скрипт не сработает т.к. регулярные выражения обрабатывают по строкам.
На этот раз регулярное выражение нашло только первый открывающийся и закрывающийся тег. В народе техника приведённая выше называется “Сетка”
Если в регулярное выражение мы добавим (.*?) то эта техника снова заработает и в случае строки без переноса:
Теперь всё работает нормально.
Предыдущие и последующие выражения
И снова начнём с примера. Данное регулярное выражение ищет строку foo за которой следует строка bar:
А теперь наоборот:
Поиск последующего выражения происходит до того, как произошло нахождение предыдущего выражения. Используйте ?
5 последних уроков рубрики «PHP»
Фильтрация данных с помощью zend-filter
Когда речь идёт о безопасности веб-сайта, то фраза «фильтруйте всё, экранируйте всё» всегда будет актуальна. Сегодня поговорим о фильтрации данных.
Контекстное экранирование с помощью zend-escaper
Обеспечение безопасности веб-сайта — это не только защита от SQL инъекций, но и протекция от межсайтового скриптинга (XSS), межсайтовой подделки запросов (CSRF) и от других видов атак. В частности, вам нужно очень осторожно подходить к формированию HTML, CSS и JavaScript кода.
Подключение Zend модулей к Expressive
Expressive 2 поддерживает возможность подключения других ZF компонент по специальной схеме. Не всем нравится данное решение. В этой статье мы расскажем как улучшили процесс подключение нескольких модулей.
Совет: отправка информации в Google Analytics через API
Предположим, что вам необходимо отправить какую-то информацию в Google Analytics из серверного скрипта. Как это сделать. Ответ в этой заметке.
Подборка PHP песочниц
Подборка из нескольких видов PHP песочниц. На некоторых вы в режиме online сможете потестить свой код, но есть так же решения, которые можно внедрить на свой сайт.