СтатьиВведение в регулярные выражения. СинтаксисPHP отличается наличием очень мощных и гибких механизмов для работы с двумя самыми часто используемыми типами данных: строками и массивами. Однако в PHP есть еще один механизм обработки строк — я говорю о механизме регулярных выражений (regular expressions). Использование регулярных выражений во многих ситуациях поможет вам заменить кучу кода всего одной строчкой. Единственная проблема, которая обычно возникает при работе с регулярными выражениями — их очень необычный, и, поначалу, совершенно непонятный синтаксис. Поэтому я постараюсь рассказать о синтаксисе регулярных выражений по возможности более просто и подробно. Общая информацияРегулярное выражение - механизм, позволяющий задать шаблон для строки и осуществить поиск данных, соответствующих этому шаблону в заданном тексте. Кроме того, дополнительные функции по работе с regexp'ами позволяют получить найденные данные в виде массива строк, произвести замену в тексте по шаблону, разбиение строки по шаблону и т.п. Однако главной их функцией, на которой основаны все остальные, является именно функция поиска в тексте данных, соответствующих шаблону, описанному в синтаксисе регулярных выражений. Очень часто регулярные выражения используются для того, чтобы проверить, является ли данная строка строкой в необходимом формате. Например следующий regexp предназначен для проверки того, что строка содержит корректный e-mail адрес: /^\w+([\.\w]+)*\w@\w((\.\w)*\w+)*\.\w{2,3}$/ Выглядит, на первый взгляд, довольно страшно :-) Но, тем не менее, это работает, и работает очень хорошо. А когда вы научитесь писать и использовать regexp'ы в своем коде — это еще будет и сильно облегчать вам жизнь. Регулярные выражения пришли к нам изUnix и Perl. В PHP существует два различных механизма для обработки регулярных выражений: POSIX-совместимые и Perl-совместимые. Их синтаксис во многом похож, однако Perl-совместимые регулярные выражения более мощные и, к тому же, работают намного быстрее (в некоторых случаях до 10 раз быстрее). Поэтому здесь мы будем вести речь только о Perl-совместимых регулярных выражениях. Кстати, необходимо заметить, что полное описание синтаксиса регулярных выражений, имеющееся в PHP Manual, занимает более 50 килобайт и, естественно, здесь мы не будем рассматривать весь синтаксис. Нам необходимы только основы, которые помогут вам понять, как именно пишутся регулярные выражения. Сутью механизма регулярных выражений является то, что они позволяют задать шаблон для нечеткого поиска по тексту. Например, если перед вами стоит задача найти в тексте определенное слово, то с этой задачай хорошо справляются и обычные функции работы со строками. Однако если вам нужно найти "то, не знаю что", о чем вы можете сказать только то, как приблизительно это должно выглядеть - то здесь без регулярных выражений просто не обойтись. Например, вам необходимо найти в тексте информацию, про которую вам известно только то, что это "3 или 4 цифры после которых через пробел идет 5 заглавных латинских букв", то вы сможете сделать это очень просто, возпользовавшись следующим регулярным выражением: /\d{3,4}\s[A-Z]{5}/ Синтаксис регулярных выражений
Регулярные выражения, как уже было сказано выше, представляют собой строку. Строка всегда начинается с символа разделителя, за которым следует непосредственно регулярное выражение, затем еще один символ разделителя и потом необязятельный список модификаторов. В качестве символа разделителя обычно используется слэш (' Основой синтаксиса регулярных выражений является тот факт, что некоторые символы, встречающиеся в строке рассматриваются не как обычные символы, а как имеющие специальное значение (т.н. метасимволы). Именно это решение позволяет работать всему механизму регулярных выражений. Каждый метасимвол имеет свою собственную роль в синтаксисе регулярных выражений. Далее мы рассмотрим все эти метасимволы.
Одним из самых важных метасимволов является символ обратного слэша ("
Существует множество символов, которые образуют метасимволы в паре с обратным слэшем. Как правило подобные пары используются для того, чтобы показать, что на этом месте в строке должен находиться символ, с кодом, который не имеет соответствующего ему изображения или же символ, принадлежащий какой-то определенной группе символов. Ниже приведены некоторые наиболее употребительные:
С остальными имеющимися метасимволами, построенными по этому принципу вы при желании сможете ознакомиться в оригинальном описании. Приведу несколько простейших примеров для того, чтобы вы понимали, о чем идет речь. Сразу оговорюсь, что примеры несколько громоздки и некрасивы, но лишь потому, что я не стал использовать в них метасимволы, о которых еще не рассказал и которые сделали бы их намного проще.
Синтаксис регулярных выражений имеет средства для определения собственных подмножеств символов. Например вам может понадобиться задать условие, что в этом месте строки должна находиться шестнадцатиричная цифра или еще что-то подобное. Для описания таких подмножеств применяются символы квадратных скобок " Есть небольшая тонкость в том, как работают метасимволы внутри квадратных скобок. Дело в том, что в синтаксисе регулярных выражений существует еще множество метасимволов, но практически все они работают только вне секций описаний подмножеств. Единственные метасимволы, которые работают внутри этих секций это:
Несколько примеров, чтобы было понятно, как это работает:
Теперь необходимо рассмотреть еще несколько метасимволов. Как уже было сказано ранее, все они работают только вне секций описчаний подмножеств символов (вне квадратных скобок).
Символы " Допустим, у нас есть текст: 12 aaa bbb aaa 27 ccc aaa aaa 45 И регулярное выражение для поиска чисел в этом тексте: /\d\d/m (не обращайте пока внимания на модификатор).
Поиск по этому регулярному выражению вернет нам 3 значения: " /^\d\d/m
Здесь результат будет только один — " /\d\d$/m вернет результат "
Символ точки "
Символ вертикальной черты " /(красное|зеленое) яблоко/
найдет в тексте все словосочетания "
Символы круглых скобок " Чтобы было понятнее, о чем я только что рассказал — рассмотрим в качестве примера то, как работает парсер регулярных выражений в случае приведенного выше регулярного выражения о яблоках: /(красное|зеленое) яблоко/
В качестве примера возьмем строку: яблоко красное и зеленое яблоко и еще одно красное яблоко и еще одно яблоко, зеленое Поиск по внутреннему регулярному выражению даст 4 результата: яблоко красное и зеленое яблоко и еще одно красное яблоко и еще одно яблоко, зеленое Однако поиск по всему регулярному выражению даст всего 2 результата, потому как в остальных случаях условия основного регулярного выражения не выполняются: яблоко красное и зеленое яблоко и еще одно красное яблоко и еще одно яблоко, зеленое
Необходимо заметить, что для этих двух случаев будет возвращен не только результат поиска по основному регулярному выражению, но и результат поиска по внутреннему регулярному выражению для каждого из найденных фрагментов. В большинстве случаев это полезно (пример — чуть позднее), но иногда наоборот, лучше избавиться от лишних результатов. В этом случае необходимо добавить символы " /(?:красное|зеленое) яблоко/ Теперь пример, когда получение результатов внутренних регулярных выражений может быть полезным. Допустим, нам необходимо проверить, является ли строка семизначным телефонным номером с указанием кода города и получить из нее код города и номер телефона: /\((\d{3,5})\)\s+(\d{3}-\d{2}-\d{2})/ Некоторые из примененных здесь метасимволов вам еще неизвестны и будут рассмотрены чуть позднее. Давайте рассмотрим этот regexp подробнее. Первая круглая скобка здесь теряет свое специальное значение и будет рассматриваться как обычный символ:
/\((\d{3,5})\)\s+(\d{3}-\d{2}-\d{2})/
Далее идет регулярное выражение в скобках (проверка кода города):
/\((\d{3,5})\)\s+(\d{3}-\d{2}-\d{2})/
После этого идет закрывающая круглая скобка, которая также лишена своего специального значения из-за символа обратного слэша, стоящего перед ней:
/\((\d{3,5})\)\s+(\d{3}-\d{2}-\d{2})/
Затем идет пропуск пустого места:
/\((\d{3,5})\)\s+(\d{3}-\d{2}-\d{2})/
И еще одно регулярное выражение в скобках, которое проверяет номер телефона:
/\((\d{3,5})\)\s+(\d{3}-\d{2}-\d{2})/
Как видите, здесь есть 3 регулярных выражения - основное и два внутренних. При этом основное выражение позволяет нам проверить, имеет ли строка необходимый нам формат, а два внутренних - получить соответственно код города и номер телефона. Т.е. одним регулярным выражением мы можем решить сразу несколько задач! Посмотрим, как работает это регулярное выражение. Пусть у нас есть строка: My phone is (095) 123-45-67 Результатами поиска будут 3 строки: (095) 123-45-67 095 123-45-67 Нам осталось рассмотреть еще одну группу метасимволов, определяющих количественные показатели (т.н. quantifiers). Как вы уже могли заметить ранее - очень часто бывает необходимо указать, что какой-то символ должен повторяться определенное количество раз. Конечно, можно просто указать его необходимое количество раз непосредственно в строке, но это, естественно не выход. Тем более, что очень часто встречаются ситуации, когда точное количество символов неизвестно. Поэтому синтаксис регулярных выражений содержит набор метасимволов, предназначенных именно для решения подобных задач. Каждый из описанных ниже метасимволов определяет количественную характеристику символа который находится непосредственно перед ним.
Звездочка "
Плюс "
Знак вопроса "
Фигурные скобки "
Есть еще одна тонкость в использовании метасимвола "
Дело в том, что по умолчанию количественные метасимволы "жадничают" и пытаются захватить как можно больший кусок текста. Если это не нужно (как в нашем случае), то необходимо "отучить" их от жадности, указав знак " Модификаторы регулярных выраженийКак уже было сказано ранее - механизм регулярных выражений позволяет добавлять модификаторы, влияющие на обработку регулярного выражения. Ниже рассмотрены наиболее употребительные, об остальных вы можете прочитать в оригинальном описании.
ЗаключениеНа этом мы заканчиваем рассмотрение синтаксиса регулярных выражений, но тема еще не закончена. В следующей статье мы рассмотрим вопросы того, как PHP работает с регулярными выражениями, а также рассмотрим некоторые практические примеры использования регулярных выражений в ваших программах. Автор: Александр Грималовский |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||