Функции регулярных выражений. PHP (регулярное выражение) - что это такое? Примеры и проверка регулярных выражений Php str replace регулярные выражения
Регулярные выражения - это специальные шаблоны для поиска подстроки в тексте. С их помощью можно решить одной строчкой такие задачи: «проверить, содержит ли строка цифры», «найти в тексте все адреса email», «заменить несколько идущих подряд знаков вопроса на один».
Начнем с одной народной программистской мудрости:
Некоторые люди, сталкиваясь с проблемой, думают: «Ага, я умный, я решу её с помощью регулярных выражений». Теперь у них две проблемы. Примеры шаблоновНачнем с пары простых примеров. Первое выражение на картинке ниже ищет последовательность из 3 букв, где первая буква это «к», вторая - любая русская буква и третья - это «т» без учета регистра (например, «кот» или «КОТ» подходит под этот шаблон). Второе выражение ищет в тексте время в формате 12:34 .
Любое выражение начинается с символа-ограничителя (delimiter по англ.). В качестве него обычно используют символ / , но можно использовать и другие символы, не имеющие специального назначения в регулярках, например, ~ , # или @ . Альтернативные разделители используют, если в выражении может встречаться символ / . Затем идет сам шаблон строки, которую мы ищем, за ним второй ограничитель и в конце может идти одна или несколько букв-флагов. Они задают дополнительные опции при поиске текста. Вот примеры флагов:
- i - говорит, что поиск должен вестись без учета регистра букв (по умолчанию регистр учитывается)
- u - говорит, что выражение и текст, по которому идет поиск, исплоьзуют кодировку utf-8, а не только латинские буквы. Без него поиск русских (и любых других нелатинских) символов может работать некорректно, потому стоит ставить его всегда.
Сам шаблон состоит из обычных символов и специальных конструкций. Ну например, буква «к» в регулярках обозначает саму себя, а вот символы значат «в этом месте может быть любая цифра от 0 до 5». Вот полный список специальных символов (в мануале php их называют метасимволы), а все остальные символы в регулярке - обычные:
Ниже мы разберем значение каждого из этих символов (а также объясним почему буква «ё» вынесена отдельно в первом выражении), а пока попробуем применить наши регулярки к тексту и посмотреть, что выйдет. В php есть специальная функция preg_match($regexp, $text, $match) , которая принимает на вход регулярку, текст и пустой массив. Она проверяет, есть ли в тексте подстрока, соответствующая данному шаблону и возвращает 0 , если нет, или 1 , если она есть. А в переданный массив в элемент с индексом 0 кладется первое найденное совпадение с регуляркой. Напишем простую программу, применяющую регулярные выражения к разным строкам:
Познакомившись с примером, изучим регулярные выражения более подробно.
Скобки в регулярных выраженияхДавай повторим, что обозначают разные виды скобок:
- Фигурные скобки a{1,5} задают число повторений предыдущего символа - в этом примере выражение ищет от 1 до 5 идущих подряд букв «a»
- Квадратные скобки означают «один любой из этих символов», в данном случае - буквы a, b, c, x, y, z или цифра от 0 до 5. Внутри квадратных скобок не работают другие спецсимволы вроде | или * - они обозначают обычный символ. Если в квадратных скобках в начале стоит символ ^ то смысл меняется на противоположный: «любой один символ, кроме указанных» - например [^a-c] значит «один любой символ, кроме a, b или c».
- Круглые скобки группируют символы и выражения. Например в выражении abc+ знак «плюс» относится только к букве c и это выражение ищет слова вроде abc, abcc, abccc. А если поставить скобки a(bc)+ то квантифиактор плюс относится уже к последовательности bc и выражение ищет слова abc, abcbc, abcbcbc
Примечание: в квадратных скобках можно указывать диапазоны символов, но помни, что русская буква ё идет отдельно от алфавита и чтобы написать «любая русская буква», надо писать [а-яё] .
БекслешиЕсли ты смотрел другие учебники по регулярным выражениям, то наверно заметил, что бекслеш везде пишут по-разному. Где-то пишут один бекслеш: \d , а здесь в примерах он повторен 2 раза: \\d . Почему?
Язык регулярных выражений требует писать бекслеш один раз. Однако в строках в одиночных и двойных кавычках в PHP бекслеш тоже имеет особое значение: мануал про строки . Ну например, если написать $x = "\$"; то PHP воспримет это как специальную комбинацию и вставит в строку только символ $ (и движок регулярных выражений не узнает о бекслеше перед ним). Чтобы вставить в строку последовательность \$ , мы должны удвоить бекслеш и записать код в виде $x = "\\$"; .
По этой причине в некоторых случаях (там, где последовательность символов имеет специальный смысл в PHP) мы обязаны удваивать бекслеш:
- Чтобы написать в регулярке \$ , мы пишем в коде "\\$"
- Чтобы написать в регулярке \\ , мы удваиваем каждый бекслеш и пишем "\\\\"
- Чтобы написать в регулярке бекслеш и цифру (\1), бекслеш надо удвоить: "\\1"
В остальных случаях один или два бекслеша дадут один и тот же результат: "\\d" и "\d" вставят в строку пару символов \d - в первом случае 2 бекслеша это последовательность для вставки бекслеша, во втором случае специальной последовательности нет и символы вставятся как есть. Проверить, какие символы вставятся в строку, и что увидит движок регулярных выражений, можно с помощью echo: echo "\$"; . Да, сложно, а что поделать?
Специальные конструкции в регулярках- \d ищет одну любую цифру, \D - один любой символ, кроме цифры
- \w соответствует одной любой букве (любого алфавита), цифре или знаку подчеркивания _ . \W соответствует любому символу, кроме буквы, цифры, знака подчеркивания.
Также, есть удобное условие для указания на границу слова: \b . Эта конструкция обозначает, что с одной стороны от нее должен стоять символ, являющийся буквой/цифрой/знаком подчеркивания (\w), а с другой стороны - не являющийся. Ну, например, мы хотим найти в тексте слово «кот». Если мы напишем регулярку /кот/ui , то она найдет последовательность этих букв в любом месте - например, внутри слова «скотина». Это явно не то, что мы хотели. Если же мы добавим условие границы слова в регулярку: /\bкот\b/ui , то теперь искаться будет только отдельно стоящее слово «кот».
Мануал- Синтаксис регулярных выражений в PHP , подробное описание
Давайте начнем с того, что такое регулярное выражение. Вот ответьте мне на вопрос, есть ли в слове "test" буква "e"? "Есть!" скажете Вы. Тогда я задаю Вам второй вопрос, как вы нашли букву "e" в слове "test"? Ответ очевиден, берем первый символ, то есть "t" сравниваем его с тем что ищем, то есть с "e". Если они не равны, то берем второй символ, то есть "e", сравниваем его с тем что ищем, то есть "e". Вуаля! Найдено совпадение. Ответ: В слове "test" есть буква "e" .
А теперь ответьте мне на еще один вопрос, где в этом примере регулярное выражение? Надеюсь Вы догадались, что регулярным выражением тут является то, что мы ищем в слове "test". То есть буква "e" в данном примере и есть регулярное выражение.
Для чего используют регулярные выражения в php? В моей практике регулярные выражения использовались, например, для определение корректно ли составлен адрес электронной почты. Так же такие выражения используют для определения корректности имя пользователя и пароля. С помощью регулярных выражений можно найти в ссылке адрес и сохранить его. Много чего можно делать Проанализировав это можно выявить главную функцию регулярных выражений, и две побочных. Главная функция , это поиск совпадений в строке. Побочные же - это сохранения найденных совпадений, и замена.
Первое регулярное выражениеВ теории мы понимаем как найти символ "e" в слове "test", как же это реализуется на практике? Для использования регулярных выражений в php обычно используют функции:
preg_match("регулярное выражение (шаблон)", "переменная в которое производится поиск", "Переменная в которое сохраняется результат поиска (не обязательный параметр)"); - Функция поиска соответствий
preg_replace("регулярное выражение (шаблон)", "На что заменить найденное совпадение", "переменная в которое производится замена"); - Функция замены
Начнем же использовать эти функции.. Вот пример поиска символа "e" в слове "test":
$a = "test";
if(preg_match("/e/",$a)) echo "найдено!!";
В коде описано условие, если в переменной $a найдено что-то по шаблону, то выдать сообщение "найдено!!" Как Вы могли заметить наш шаблон стоит между двумя "/". В данном случае символ "/" символизирует начало и конец нашего шаблона . Надеюсь это понятно.
Все это конечно интересно... но вот только наш шаблон, какой то уж очень простой, не находите? Ведь редко нам нужно найти какой то символ в переменной. В большинстве случаев нам необходимо найти много символов, при том еще и неизвестных. Как же быть? Давайте поставим себе задачку, и попробуем ее решить. Предположим у нас есть строка состоящее из цифр и одной неизвестной английской буквы
Как найти эту букву? Там может быть любая буква английского алфавита, как же ее определить? Вы сами ответили на свой вопрос, там любая буква, то есть она находится в диапазоне от a до z. В регулярных выражениях можно использовать диапазоны. Если мы не знаем какой символ ищем, но точно знаем что этот символ является буквой английского алфавита, то запись будет следующая:
$a = "123a321";
if(preg_match("//",$a)) echo "найдено!!";
Заметьте, что диапазон ставится в "[" "]" скобках. Все что заключено в такие скобки определяется как один символ, в данном случае символ варьируется в диапазоне от a до z. Если же нам понадобится найти не букву, а цифру, то запись будет такая:
$a = "abc1cba";
if(preg_match("//",$a)) echo "найдено!!";
Так же хочу заметить, что регулярные выражение чувствительны к регистру, поэтому символы "A" и "a" совершенно разные, для поиска тех и тех символов, пишут так:
$a = "123a321";
if(preg_match("//",$a)) echo "найдено!!";
Так же существует поиск русских букв, осуществляется так же как и с английскими:
$a = "123ы321";
if(preg_match("/[а-яА-Я]/",$a)) echo "найдено!!";
Мы научились искать неизвестный символ в строке. Что же делать если нам необходимо найти несколько символов? На помощь приходят так называемые метасимволы... Предположим у нас есть строка с циферками, буковками, как ее описать в шаблоне? Можно так:
строка - 123а321
шаблон -
Хм... шаблон и вправду подходит к нашей строке, и при проверки на соответствие даст долгожданное true! Но какая то громоздкая запись, Вам не кажется?
Вот как ее можно сократить:
строка - 123а321
шаблон - *
Мне кажется так покороче Что же из себя представляет символ "*"? Это и есть тот самый метасимвол, он означает что описанный нами символ (а именно символ который может содержать цифры от 0 до 9 или буквы английского алфавита, от a до z) может повторяться до бесконечности раз, или же не одного раза. Да да! Этот метасимвол, найдет совпадение в пустой переменной, так как даже отсутствие описанного нами символа выдаст true! Запомните это
Какие еще бывают метасимволы?
Например метасимвол "+" Он почти что схож с метасимволом "*" за одним маленьким исключением. "*" выдаст true даже при отсутствия символа, а "+" проверит на наличие хотя бы одного символа. То есть если в строке необходимо наличие минимум одного символа то используйте "+" вместо "*"
Так же часто используют метасимвол "?" Он означает что в строке должно находится не более одного искомого символа. Давайте я приведу пару примеров для двух последних, описанных мной метасимволов.
Предположим нам необходимо проверить на корректность пароль пользователя. Давайте подумаем что должен содержать пароль пользователя? Ну во-первых он должен быть не меньше одного символа. Во-вторых он должен содержать только цифры и буквы английского алфавита, стало быть регулярное выражение будет выглядеть вот так:
$a = "qwerty12345";
Какие символы мы разрешили? Английские буквы любого регистра и цифры. Теперь попробуйте вместо пароля оставить пустую строчку.
$a = "";
if(preg_match("/+/",$a)) echo "Пароль верный";
Вам не высветится сообщение "Пароль верный". Почему? Потому что метасимвол "+" проверил строку на наличие хотя бы одного символа.
А теперь небольшой фокус, давайте взглянем на наше выражение, мы ведь не разрешали в нем, ну скажем пробел, ведь так? поставьте пробел в конце пароля и запустите
$a = "qwerty12345 ";
if(preg_match("/+/",$a)) echo "Пароль верный";
И почему мы видим наше сообщение о корректном пароле? Все довольно просто... Функция preg_match(); останавливает свою проверку при первом же совпадение. То есть символ "q" подходит под описанный нами шаблон, а все остальное для функции уже не важно Что же делать? Вот как это исправить:
$a = "qwerty12345 ";
if(preg_match("/^+$/",$a)) echo "Пароль верный";
Добавляя "^" в начале выражения и "$" в конце, мы говорим функции, что шаблону должна соответствовать вся строка. Если вы запустите этот код, то сообщения не увидите, так как в конце пароля стоит недопустимый символ - пробел
Теперь смените метасимвол "+" на метасимвол "?". Как Вы думаете что произойдет? Правильно сообщение о корректности пароля будет отсутствовать, так как в пароле более одного символа. Надеюсь я нормально объяснил работу, этих трех, часто используемых, метасимволов
Иногда "не" лучшеМы как минимум научились проверять правильность пароля, и это хорошо! Давайте я Вам расскажу про еще одни способ поиска чего либо в строке. Вот скажем нам нужно проверить отсутствие в строке цифр. Как это сделать? Вот строка:
(Я специально ввел в нее эти "-_+()" символы что бы жизнь медом не казалась... ) Мы могли бы составить следующее выражение:
Но согласитесь, ведь мы не всегда знаем какие символы используются в строке, но нам точно известно, что цифр в ней быть не должно! Стало быть логичнее было бы просто написать шаблон, который пропускал бы строки в которых нет цифр, а не те, в которых присутствует "О боже мой сколько же не понятных символов!!!" . Вот пример правильно составленного выражения для таких задач:
$a = "a-_+()";
if(preg_match("/^[^0-9]+$/",$a)) echo "Цифр нет!";
Как же мы этого добились? Мы ввели символ , но! поставленная в начале крышка "^" ([^0-9]) говорит о том, что в строке этого символа быть не должно Надеюсь с этим разобрались
Ну что ж, давайте потихоньку закругляться... Я приведу два примера с объяснениями, в ходе которых мы научимся сохранять результат поиска в переменную, и научимся проверять на корректность почтовый адрес
Увидел, сохранил!Мой блог
$a = "Мой блог";
preg_match("//", $a);
В нашем регулярном выражение мы описали все возможные символы которые могут входить в ссылку. Так же хочу обратить внимание на символы кавычки и "/" в нашем выражение.. Перед ними стоит обратный слеш, для чего он? Дело в том что "/" и кавычка сами по себе спецсимволы. И для того что бы шаблон их воспринял как обычные символы, нам необходимо их экранизировать. Экранизация проводится путем добавление перед спецсимволами обратный слеш. Надеюсь понятно
$a = "Мой блог";
preg_match("//", $a, $b);
Ну и соответственно необходимо дописать дополнительный параметр в виде переменной $b, в ней и будет храниться найденная ссылка. Так же необходимо знать, что результат поиска помещается в массив. Стало быть переменная $b - массив. Искомая нами информация находится под индексом 1. А это означает, что результат поиска в переменной $b. выведем результат на экран:
$a = "Мой блог";
preg_match("//", $a, $b);
echo $b;
Ну и на по следок, ответ на вопрос, корректный ли e-mail? Для начала, необходимо узнать, какие символы разрешены в адресах? Насколько мне известно в разрешенные символы входят:
- английские буквы, цифры, "_", "-" эмммм вроде все... Будем исходить их этого.
- Дальше у нас идет "@"
- После, английские буквы
- Далее, точка
- И опять английские буквы...
Стало быть регулярное выражение будет следующим:
$a = "[email protected]";
if(preg_match("/^+@+.+$/", $a)) echo "e-mail адрес составлен корректно!";
else echo "e-mail адрес составлен НЕ корректно!";
Ну что ж... Буду надеется, что такие записи теперь не пугают Вас, и Вы в них вполне можете разобраться.
На по следок хочу кое что сказать. Статья получилось громоздкой, и в то же время охватила лишь часть возможностей. Если вы читаете это предложение, то скорее всего прочли ее до конца, от чего большое Вам спасибо
Что касается цикла статей о разработке cms блога , первую часть цикла оглашаю закрытой! В скором будущем мы начнем реализовывать админ панель, так что не "переключайтесь" Если у Вас есть какие то вопросы, с удовольствием отвечу. Всего Вам самого наилучшего, у меня все!
В PHP существует несколько функций для работы с регулярными выражениями. Все они используют один и тот же парсер регулярных выражений для своей работы, но при этом преследуют различные цели. Ниже мы рассмотрим все эти функции. Я буду приводить описание синтаксиса каждой функции в том виде, в котором она описана в PHP Manual , чтобы вам легче было разобраться.
Функция preg_match()Синтаксис:
Int preg_match (string pattern, string subject [, array matches])
Эта функция предназначена для проверки того, совпадает ли заданная строка (subject) с заданным регулярным выражением (pattern). В качестве результата функция возвращает 1 , если совпадения были найдены и 0 , если нет. Если при вызове функции был задан необязательный параметр matches , то после работы функции ему будет присвоен массив, содержащий результаты поиска по заданному регулярному выражению. Заметьте, что вне зависимости от того, сколько именно совпадений было найдено при поиске - вам будет возвращено только первое совпадение. Рассмотрим пример того, как это работает:
Matches: 1 Array ( => 123)
Если вы внимательно прочитали предыдущий выпуск и понимаете, как работают регулярные выражения, то вы должны заметить, что реально функция preg_match() обнаружила в заданной строке 5 совпадений с заданным выражением, но вернула только первое из них. Казалось бы, что в этом случае было бы логичнее возвращать результаты поиска в виде строки, а не в виде массива, но это не так. Вспомните, что регулярное выражение может содержать в себе внутренние регулярные выражения, которые также возращают результат. А для того, чтобы вернуть результаты поиска по всем регулярным выражениям нам как раз и требуется массив. Для того, чтобы проиллюстрировать сказанное выше давайте немного изменим регулярное выражение и посмотрим на результат:
Результат будет следующим:
Matches: 1 Array ( => 123 => 2)
Как видите - здесь присутствуют результаты поиска по всем имеющимся регулярным выражениям.
Функция preg_match_all()Синтаксис:
Int preg_match_all (string pattern, string subject, array matches [, int order])
Эта функция очень похожа на предыдущую и предназначена для тех же самых целей. Единственное ее отличие от preg_match() состоит в том, что она осуществляет "глобальный" поиск в заданном тексте по заданному регулярному выражению и, соответственно, находит и возвращает все имеющиеся совпадения. Посмотрим, как отличается работа этой функции на том же самом примере:
Результат работы:
Matches: 5 Array ( => Array ( => 123 => 234 => 345 => 456 => 567))
Как видите - здесь мы получили все найденные совпадения и их количество в качестве результата.
Необходимо обратить ваше внимание на дополнительный параметр, появившийся в этой функции по сравнению с preg_match() : order . Значение этого параметра определяет структуру выходного массива с найденными совпадениями. Его значение может быть одним из перечисленных ниже:
- PREG_PATTERN_ORDER - результаты поиска будут сгруппированы по номеру регулярного выражения, которое возвратило этот результат (это значение используется по умолчанию).
- PREG_SET_ORDER - результаты поиска будут сгруппированы по месту их нахождения в тексте
Для того, чтобы лучше понять разницу между этими значениями, посмотрим на результат работы одного и того же скрипта при использовании каждого из них:
Сначала посмотрим на то, как выглядит результат при использовании PREG_PATTERN_ORDER:
Результат:
Array ( => Array ( => 123 => 234 => 345 => 456 => 567) => Array ( => 2 => 3 => 4 => 5 => 6))
Как видите - массив результатов содержит внешние индексы, соответствующие номерам регулярных выражений, от которых получен результат (индекс 0 имеет основное регулярное выражение). По этим индексам в массиве расположены массивы, содержащие непосредственно найденную информацию, причем индекс в этом внутреннем массиве соответствует "порядковому номеру" данного фрагмента в исходном тексте.
Теперь попробуем то же самое, но с PREG_SET_ORDER:
Результат:
Array ( => Array ( => 123 => 2) => Array ( => 234 => 3) => Array ( => 345 => 4) => Array ( => 456 => 5) => Array ( => 567 => 6))
Как видите - здесь основной массив содержит результаты поиска, сгруппированные по порядку их нахождения в тексте, причем каждый результат представляет собой массив с результатами поиска по этому найденному фрагменту для всех имеющихся регулярных выражений.
Функция preg_replace()Синтаксис:
Mixed preg_replace (mixed pattern, mixed replacement, mixed subject [, int limit])
Эта функция позволит вам произвести замену текста по регулярному выражению. Как и в предыдущих функциях, здесь производится поиск по регулярному выражению pattern в тексте subject , и каждый найденный фрагмент текста заменяется на текст, заданный в replacement . Задание необязятельного параметра limit позволит ограничить количество заменяемых фрагментов в тексте.
Например, нам необходимо "сжать" текст, убрав из него все лишние пробелы и символы перевода строки:
Результатом работы данной программы будет следующий текст:
Перед заменой: there is some text just for test После замены: there is some text just for testКак видите - всего одна строчка позволила нам решить достаточно нетривиальную в обычной практике задачу. Объяснять само регулярное выражение я не буду, если вы внимательно прочитали предыдущий выпуск - понять его вам будет несложно.
Однако основная прелесть этой функции, которая и придает ей всю ее мощь - это тот факт, что вы можете ссылаться на результаты поиска при генерации замещающего текста. В качесте примера покажу, как можно очень быстро и элегантно решить задачу, которая возникает достаточно часто - конвертация дат из одного формата в другой. Как вы знаете, на Западе обычно используется формат mm/dd/yyyy , тогда как у нас обычно - dd.mm.yyyy . Следующий пример осуществляет конвертацию дат между этими форматами в заданном тексте:
Результат работы этой программы:
Today is 16.11.2001
Обратите внимание на текст, используемый для замены. В нем использованы т.н. backreferences , т.е. ссылки на найденный ранее текст. Всего таких ссылок может быть не более 100 с номерами от 0 до 99 (соответственно в тексте они выглядят как \0 , \1 , \2 ... \99). Backreference с номером 0 будет заменена на весь найденный текст, \1 - на текст, найденный первым внутренним регулярным выражением, \2 - вторым и т.д. Номерв внутренним регулярным выражениям присваиваются по мере их находжения в тексте, т.е. слева-направо. В нашем случае \1 - это месяц, \2 - день, \3 - год.
Помимо стандартного синтаксиса регулярных выражений, в PHP , совместно с функцией preg_replace() используется еще один дополнительный модификатор - " e ". Его использование заставляет PHP рассматривать текст замены не как текст, а как PHP код, что дает возможность еще больше расширить сферу применения этой функции в вашем коде. Следующий пример демонстрирует использование этого модификатора - он производит замену всех целых десятичных чисел в тексте на их шестнадцатиричные эквиваленты:
Результатом работы этой программы будет:
0x7b 0xea 0x159 0x1c8 0x237
И еще одно. Функция preg_replace() также умеет работать с массивами регулярных выражений. Т.е. это позволит вам осуществить поиск и замену сразу по множеству условий! В качестве примера приведу фрагмент кода, описанный в PHP Manual и осуществляющий конвертацию HTML документа в текст при помощи всего лишь одного вызова preg_replace() !
// $document should contain an HTML document. // This will remove HTML tags, javascript sections // and white space. It will also convert some // common HTML entities to their text equivalent. $search = array (""]*?>.*?"si", // Strip out javascript """si", // Strip out html tags ""([\r\n])[\s]+"", // Strip out white space ""&(quot #34);"i", // Replace html entities ""&(amp #38);"i", ""&(lt #60);"i", ""&(gt #62);"i", ""&(nbsp #160);"i", ""&(iexcl #161);"i", ""&(cent #162);"i", ""&(pound #163);"i", ""&(copy #169);"i", ""(\d+);"e"); // evaluate as php $replace = array ("", "", "\\1", "\"", "&", "", " ", chr(161), chr(162), chr(163), chr(169), "chr(\\1)"); $text = preg_replace ($search, $replace, $document);Сами по себе регулярные выражения очень просты, интересно лишь их совместное использование для решения общей задачи.
Функция preg_replace_callback()Синтаксис:
Mixed preg_replace_callback (mixed pattern, mixed callback, mixed subject [, int limit])
Эта функция является расширенной версией функции preg_replace() (хотя, казалось бы, чего еще можно пожелать?). Единственным отличием ее от preg_replace() является то, что в качестве текста для замены в ней задается не сам текст, а имя функции, которая будет производить обработку найденного текста и возвращать замещающий текст. Т.е. с использованием этой функции мощь инструментария PHP по обработке текста становится поистине безграничной! В качестве примера хочу привести фрагмент кода, который выполняет работу, аналогичную той, что производится механизмом сессий в PHP : добавление дополнительного аргумента (идентификатора сессии) к каждой ссылке внутри HTML документа.
Пример может показаться немного громоздким, но это исключительно из-за обилия комментариев.
Функция preg_split()Синтаксис:
Array preg_split (string pattern, string subject [, int limit [, int flags]])
Данная функция выполняет действие, аналогичное функциям split() и explode() - разбивает строку на части по какому-либо признаку и возвращает массив, содержащий части строки. Однако ее возможности по заданию правил разбиения больше, чем у этих функций, потому что в ее основе лежит механизм регулярных выражений, в мощи которого, я надеюсь, вы уже смогли убедиться. Если говорить более конкретно, то строка subject разбивается на части по разделителю, заданному регулярным выражением pattern . При этом количество фрагментов может быть ограничего необязятельным параметром limit . Кроме того эта функция поддерживает необязательный параметр flags , который позволяет в некоторой степени контролировать процесс разбиения строки.
Параметр flags может принимать следующие значения (или их комбинации с использованием знака " "):
- PREG_SPLIT_NO_EMPTY - возвращать только непустые части строк, полученные в результате разбиения.
- PREG_SPLIT_DELIM_CAPTURE - возвращать также результаты поиска по внутренним регулярным выражениям.
Рассмотрим пару примеров. Для начала - выражение, которое разбивает произвольный текст на отдельные слова:
Как видите - мы получаем содержимое файла " my_text.txt " в виде строки, разбиваем его на отдельные слова и выводим содержимое массива слов, чтобы убедиться, что все работает правильно.
Еще один пример производит разбиение заданного слова на буквы (он описан в PHP Manual):
Значение -1 для параметра limit означает отсутствие лимита.
Функция preg_quote()Синтаксис:
String preg_quote (string str [, string delimiter])
Эта функция - единственная, не относящаяся непосредственно к механизму регулярных выражений. Ее назначение - "квотинг" символов, имеющих специальное значение в синтаксисе регулярных выражений. Обычно это символы:
. \ + * ? [ ^ ] $ () { } = ! < > :Все эти символы, встречающиеся в строке будут "отквочены" путем добавления символа " \ " непосредственно перед каждым из них. Модифицированная таким образом строка будет возвращены в качестве результата.
Эта фцнкция также имеет необязательный параметр delimiter . Если этот параметр задан, то символ, переданный в качестве этого параметра тоже будет "отквочен" данной функцией.
Функция preg_grep()Синтаксис:
Array preg_grep (string pattern, array input)
Действие этой функции похоже на действие команды grep в Unix. Она ищет текст по регулярному выражению pattern , в массиве input и возвращает новый массив, содержащий только элементы, в которых были найдены совпадения с заданным регулярным выражением. К примеру у нас есть файл, содержащий в каждой строке числовую и текстовую информацию. Нам необходимо получить из этого файла только строки, содержащие числа:
Одна из очень мощных и полезных возможностей языка PHP - поддержка регулярных выражений. Многих программистов, как начинающих, так и довольно опытных, пугает внешняя сложность и запутанность языка регулярных выражений. Но могу вас уверить - это того стоит. Применение регулярных выражений существенно облегчает работу по обработке текстов и слабо структурированных данных.
Регулярные выражения - это выражения, написанные на специальном языке. Не пугайтесь, язык достаточно прост для понимания, необходимы лишь опыт и практика.
Я думаю, вы неоднократно сталкивались с ситуациями, когда у вас есть текст (например, в Microsoft Word) и вам надо найти в нём что-то важное. Если вы знаете, что именно ищете - всё просто: вызвали диалог поиска, ввели искомое слово, нажали кнопку и вуаля - текст найден.
Но что вы будете делать, если вы заранее знаете только тип искомой информации? Например, перед вами стоит задача найти все адреса электронной почты в документе на пару сотен листов. Некоторые будут просматривать документ вручную, некоторые - введут в поиске собаку (@) и будут искать её. Согласитесь - оба вариата это каторжный неблагодарный труд.
Вот тут-то на выручку приходят регулярные выражения. В некотором приближении регулярные выражения можно сравнить с масками или шаблонами, которые накладываются на текст: если текст соответствует маске - значит это искомый фрагмент. Но перед тем как рассматривать применение регулярных выражений, мы познакомимся с их синтаксисом.
Регулярное выражение - это текстовая строка, составленная по определённым законам и правилам. Строка состоит из символов и групп символов, метасимволов, квантификаторов и модификаторов.
Под символами в данном случае понимаются любые символы любого алфавита. Причем не только читаемые. Вы вполне можете вставить в выражение нечитаемый символ, для этого вам надо будет всего-лишь знать его код в шестнадцатиричном виде. Например:
// читаемые символы a Е // нечитаемые символы и коды \x41 - то же что буква "A" \x09 - символ табуляции
Группа символов - это несколько символов, записанные последовательно:
Абвг ACZms
Сразу обращаю ваше внимание - "пробел" в регулярных выражения тоже рассматривается как значимый символ, поэтому при написании выражений будьте внимательны. Например, эти граппы символов являются РАЗНЫМИ выражениями:
АБВГДЕ АБВ ГДЕ
Следующий элемени языка - метасимволы. Приставка "мета" означает, что эти символы описывают некие другие символы или их группы. В таблице рассмотрены основные метасимволы языка регулярных выражений:
Метасимволы для задания специальных символов | |
() | Скобки. Определяют вложенные выражения. |
| | Метасимвол выбора |
^ | Метасимвол начала строки |
$ | Метасимвол конца строки |
\n | Символ перевода строки (шестнадцатеричный код 0x0A) |
\r | Символ возврата каретки (шестнадцатеричный код 0x0D) |
\t | Символ табуляции (шестнадцатеричный код 0x09) |
\xhh | Вставка символа с шестнадцатиричным кодом 0xhh, например \x42 вставит латинскую букву "B" |
Метасимволы для задания групп символов | |
. | Точка. Любой символ. |
\d | Цифра (0-9) |
\D | Не цифра (любой символ кроме символов 0-9) |
\s | Пустой символ (обычно пробел и символ табуляции) |
\S | Непустой символ (все, кроме символов, определяемых метасимволом \s) |
\w | "Словарный" символ (символ, который используется в словах. Обычно все буквы, все цифры и знак подчеркивания ("_")) |
\W | Все, кроме символов, определяемых метасимволом \w |
Метасимволы из второй половины таблицы очень легко запомнить. "d" - digit (цифра), "s" - symbol (символ), "w" - word (слово). Если буква большая - значит надо добавить "НЕ" в описанию группы.
Возьмём для примера текст "На красной майке цифры 1812, а на зелёной майке - 2009". Рассмотрим примеры простейших регулярных выражений:
\d\d\d\d - найдёт 1812 и 2009 \D - найдёт все буквы, пробелы и знаки препинания \s - найдёт все пробелы в тексте.
Но ведь год в нашем примере может быть записан не четырьмя, а двумя цифрами, слова могут иметь другие склонения и т.д. Здесь могут помочь подмножества символов, которые задаются при помощи квадратных скобок:
Означает любую цифру (то же, что \d) - означает чётную цифру - обозначает любой символ латниского алфавита (в любом регистре) или цифру.
Например, выражение \d\d\d в тестовой строке найдёт только 1812, но не 2009. Это выражение следует читат как "найти все последовательности из четырёх цифр, где последняя цифра равна 0,2,4,6 или 8".
Нам осталось упомянуть лишь квантификаторы и модификаторы.
Квантификатор - это специальная конструкция, определяющая, сколько раз должен встретиться символ или группа символов. Квантификатор записывается в фигурных скобках "{}". Возможны два формата записи: точный и диапазонный. Точный формат записывается так:
Здесь Х - это количество раз, которое должен повториться предшествующий символ или группа. Например выражение
Вторая форма записи - диапазонная. Записывается как
{X, Y} // или {,Y} // или {X,}
где X - минимальное, а Y - максимальное количество повторений. Например:
читается как "от двух до четырёх последовательно записанных цифр". Если одна из границ не указана, то подразумевается отсутствие ограничения. Например:
\w{3,} - три и более букв. \d{,5} - цифр нет вообще, либо есть, но не более пяти.
Квантификаторы могут применяться как к одному символу, так и к группе:
[ А-Яа-я ]{1,3}
Эта конструкция выберет из текста все русские слова из одной, двух или трёх букв (например, "или", "не", "я", "иду" и т.п.)
Кроме фигурных скобок с уществует ещё три метасимвола-квантификатора: "*" (звёздочка), "+" (плюс) и "?" (вопрос). Их испльзуют в случаях, когда заранее неизвестно минимальное и максимальное количество необходимых повторений. Например, при поиске адресов электронной почты нельзя заранее сказать, сколько символов будет в имени пользователя (до "собаки"), а сколько - в имени домена (после "собаки").
Метасимвол "*" читается как "любое количество от нуля и более", т.е. конструкция
определяет любое количество последовательных букв, в том числе и их полное отсутствие.
Символ "+" отличается от звёздочки лишь тем, что требует наличия хотя-бы одного символа. Т.е. конструкция
соответствует любой цифровой последовательности, где цифр одна или более.
Символ "?" соответствует отсутствию или наличию единственного символа. Т.е. конструкция
соответствует любой цифровой последовательности, где цифр одна или две.
Здесь стоит упомянуть о такой особенности антификаторов "*" и "+" как жадность . Суть в том, что по-умолчанию эти символы соответствуют максимально длинной последовательности символов. Например, для строки "мама мыла раму" выражение:
выберет "мама мыла ра", что несколько неожиданно, ведь мы предполагали получить "ма". Для изменения такого поведения используется метасимвол "?" (знак вопроса), записанный сразу после квантификатора. Он органичивает "аппетит" квантификаторов, заставляя их возвращать первое совпадение, а не самое длинное. Теперь изменим предыдущий пример:
и получим требуемое совпадение "ма".
Последний элемент языка - модификаторы . Модификатор - это спецсимвол, определяющий "системные" параметры анализа регулярных выражений. Таких символов всего четыре, они могут применяться как по отдельности, так и одновременно:
i | Включает режим case-insensitive, т.е. большие и маленькие буквы в выражении не различаются. |
m | Указывает на то, что текст, по которому ведется поиск, должен рассматриваться как состоящий из нескольких строк. По умолчанию механизм регулярных выражений рассматривает текст как одну строку вне зависимости от того, чем она является на самом деле. Соответственно метасимволы "^" и "$" указывают на начало и конец всего текста. Если же этот модификатор указан, то они будут указывать соответственно на начало и конец каждой строки текста. |
s | По умолчанию метасимвол "." не включает в свое определение символ перевода строки. Т.е. для многострочного текста выражение /.+/ вернет только первую строку, а не весь текст, как ожидается. Указание этого модификатора снимает это ограничение. |
U | Делает все количественные метасимволы "не жадными" по умолчанию. В некоторых модификациях языка (в частности в PHP) вместо "U" используется символ "g", более соответствующий смыслу ("g" - сокращение от английского "greedy", "жадный"). |
В таблице приведены наиболее популярные и нужные примеры регулярных выражений. Некторые из них могут показаться вам сложными и громоздкими, но при детальном изучении вы без сомнения разберётесь.
Регулярные выражения в PHP.Для работы с регулярными выражениями в PHP предназначены специальные функции, спосок которых и краткое описание приведены в таблице:
int preg_match (string pattern, string subject [, array matches]) |
Функция проверяет, совпадает ли содержимое subject с шаблоном pattern. Возвращает 1, если совпадения найдены, иначе возвращает 0. Если указать необязательный параметр-массив matches, то при выполнении функции в него будут занесен единственный элемент - первое найденное совпадение.
|
int preg_match_all (string pattern, string subject, array matches [, int order]) |
Функция идентична предыдущей, с единственным отличием - она производит поиск по всему тексту и возвращает в массиве matches ВСЕ найденные совпадения. |
mixed preg_replace (mixed pattern, mixed replacement, mixed subject [, int limit]) |
Как и обе предшествующие функции, preg_replace производит поиск фрагмента текста, соответствующего шаблону. Все найденные фрагменты функция заменяет на указанный в параметрах текст. |
mixed preg_replace_callback (mixed pattern, mixed callback, mixed subject [, int limit]) |
Функция является расширенной версией предыдущей. Главное отличие - этой функции в параметрах передаётся имя функции, которая будет анализировать текст и формировать замещающий текст. |
array preg_split (string pattern, string subject [, int limit [, int flags]]) |
Эта функция аналогична функциям explode() и split(). Её особенность в том, что в качестве разделителя выступает не фиксированная строка, а регулярное выражение. Функция разбивает исходные данные на элементы и помещает их в выходной массив. |
array preg_grep (string pattern, array input) |
Функция предназначена для регулярного поиска в массивах. Для поиска задаётся шаблон и массив входных данных, а возвращается массив, состоящий только из элементов, соответствющих шаблону. |
Рассмотренный список функций далеко не полон, но вполне достаточен для успешного начала работы с регулярными выражениями. Если вы заинтересовались этой темой - обязательно почитайте дополнительную литературу (например, книгу Фридла "Регулярные выражения"). Кроме того, в целях обучения рекомендую поставить одну из специальных программ для тестирования регулярных выражений (например, "PCRE" или "RegEx Builder").
Регулярные выражения — очень полезный инструмент для разработчиков. Регулярные выражения позволяют проверять правильность текста, искать и изменять его.
В этой статье собраны некоторые очень полезные выражения, с которыми часто приходится работать.
При первом знакомстве с регулярными выражениями может показаться, что их сложно понять и применять. На самом деле все проще, чем кажется. Перед тем как приступить к рассмотрению сложных примеров, разберем основы:
Функции для работы с регулярными выражениями в PHP Проверка доменаПроверка на правильное доменное имя.
$url = "http://example.com/"; if (preg_match("/^(http|https|ftp)://(*(?:.*)+):?(d+)?/?/i", $url)) { echo "Ok."; } else { echo "Wrong url."; }
Подсветка слов в текстеОчень полезное регулярное выражение для . Пригодится для поиска.
$text = "Sample sentence, regex has become popular in web programming. Now we learn regex. According to wikipedia, Regular expressions (abbreviated as regex or regexp, with plural forms regexes, regexps, or regexen) are written in a formal language that can be interpreted by a regular expression processor"; $text = preg_replace("/b(regex)b/i", "1", $text); echo $text;
Подсветка результатов поиска в WordPressКак уже было сказано, предыдущий пример очень полезен при . Применим его к WordPress. Откройте файл search.php, найдите функцию the_title(). Замените её следующим:
Echo $title;
Теперь, перед этой строкой вставьте код:
Откройте файл style.css . Добавьте в него строку:
Strong.search-excerpt { background: yellow; }
Получить все изображения из HTML документаЕсли вам когда-нибудь понадобиться найти все изображения на HTML странице, вам пригодится следующий код. С его помощью можно легко создать загрузчик изображений, используя .
$images = array(); preg_match_all("/(img|src)=("|")[^"">]+/i", $data, $media); unset($data); $data=preg_replace("/(img|src)("|"|="|=")(.*)/i","$3",$media); foreach($data as $url) { $info = pathinfo($url); if (isset($info["extension"])) { if (($info["extension"] == "jpg") || ($info["extension"] == "jpeg") || ($info["extension"] == "gif") || ($info["extension"] == "png")) array_push($images, $url); } }
Удаление повторяющихся слов (не зависимо от регистра) $text = preg_replace("/s(w+s)1/i", "$1", $text); Удаление повторяющихся знаков препинанияПохоже на предыдущее, только удаляет знаки препинания.
$text = preg_replace("/.+/i", ".", $text);
Нахождение XML/HTML тегаПростая функция, которая принимает два аргумента: тег, который необходимо найти, и строка, содержащая XML или HTML.
Function get_tag($tag, $xml) { $tag = preg_quote($tag); preg_match_all("{]*>(.*?)."}", $xml, $matches, PREG_PATTERN_ORDER); return $matches;
Нахождение XML/HTML тега с определенным значением атрибутаФункция похожа на предыдущую, но появляется возможность указать атрибут тега. Например: .
Function get_tag($attr, $value, $xml, $tag=null) { if(is_null($tag)) $tag = "\w+"; else $tag = preg_quote($tag); $attr = preg_quote($attr); $value = preg_quote($value); $tag_regex = "/]*$attr\s*=\s*". "(["\"])$value\\2[^>]*>(.*?)/" preg_match_all($tag_regex, $xml, $matches, PREG_PATTERN_ORDER); return $matches; }
Нахождение шестнадцатеричных кодов цветаФункция позволяет находить или проверять правильность шестнадцатеричных кодов цвета.
$string = "#555555"; if (preg_match("/^#(?:(?:{3}){1,2})$/i", $string)) { echo "example 6 successful."; }
Нахождение заголовка страницыДанный код найдет и выведет на экран текст между тегами и HTML страницы.
$fp = fopen("http://www.catswhocode.com/blog","r"); while (!feof($fp)){ $page .= fgets($fp, 4096); } $titre = eregi("(.*)",$page,$regs); echo $regs; fclose($fp);
Парсинг логов ApacheМногие сайты работают на веб-сервере Apache. Если ваш сайт тоже работает на тако сервере, то следующие регулярки могут пригодиться.
//Logs: Apache web server // Успешные доступы к html файлам. Полезно для подсчета показов страниц. "^((?#client IP or domain name)S+)s+((?#basic authentication)S+s+S+)s+[((?#date and time)[^]]+)]s+"(?:GET|POST|HEAD) ((?#file)/[^ ?"]+?.html?)??((?#parameters)[^ ?"]+)? HTTP/+"s+(?#status code)200s+((?#bytes transferred)[-0-9]+)s+"((?#referrer)[^"]*)"s+"((?#user agent)[^"]*)"$" //Logs: Apache web server //404 ошибки "^((?#client IP or domain name)S+)s+((?#basic authentication)S+s+S+)s+[((?#date and time)[^]]+)]s+"(?:GET|POST|HEAD) ((?#file)[^ ?"]+)??((?#parameters)[^ ?"]+)? HTTP/+"s+(?#status code)404s+((?#bytes transferred)[-0-9]+)s+"((?#referrer)[^"]*)"s+"((?#user agent)[^"]*)"$" }
Замена двойных кавычек на фигурные preg_replace("B"b([^"x84x93x94rn]+)b"B", "?1?", $text); Проверка сложности пароляЭто регулярное выражение проверяет строку по пунктам: строка должна содержать не менее 6 букв, цифр, подчеркиваний и тире. Строка должна содержать хотя бы одну заглавную букву, строчную и цифру.
"A(?=[-_a-zA-Z0-9]*?)(?=[-_a-zA-Z0-9]*?)(?=[-_a-zA-Z0-9]*?)[-_a-zA-Z0-9]{6,}z"
WordPress: Получение изображений поста с помощью регулярного выраженияЕсли вы используете WordPress вам может пригодиться функция, которая получит все изображения из поста и покажет их. Для использования данного кода, скопируйте его в файлы своей темы.