PDA

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


usman
25.02.2009, 11:11
Регулярные выражения - это система синтаксического разбора текстовых фрагментов по формализованному шаблону, основанная на системе записи образцов для поиска. Образец (pattern), задающий правило поиска, по-русски также иногда называют «шаблоном», «маской».Если вы работали с Norton/Volkov/Windows Commander или Far, то знаете такую вещь как wildcards. Например: delete c:\windows\*.* удаляет все файлы из указанной директории. В именах файлов особых изощрений делать не приходится, поэтому система простая: символ * означает любой набор символов, в том числе пустой (*.txt), символ ? - любой символ или никакого символа (document?.txt) и так далее, хоть вариантов не так и много.

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

Итак, задача системы - помимо четко заданных символов ("Вася(.*)Пупкин") позволить указать пользователю поиск заданного количества заданных символов. В приведенном примере с Васей Пупкиным между словами задано любое количество любых символов. Если надо найти шесть цифр, то пишем "[0-9]{6}" (если, например, от шести до восьми цифр, тогда "[0-9]{6,8}"). К чему это все? К тому, что в отличие от wildcard из операционной системы, здесь разделены такие вещи как указатель набора символов и указатель необходимого количества: <набор символов><квантификатор> Вместо набора символов может быть использовано обозначение любого символа - точка, может быть указан конкретный набор символов (поддерживаются последовательности - упоминавшиеся "0-9"). Может быть указано "кроме данного набора символов".

Указатель количества символов в официальной документации по php называется "квантификатор". Термин удобный и не несет в себе кривотолков. Итак, квантификатор может иметь как конкретное значение - либо одно фиксированное ("{6}"), либо как числовой промежуток ("{6,8}"), так и абстрактное "любое число, в т.ч. 0" ("*"), "любое натуральное число" - от 1 до бесконечности ("+": "document[0-9]+\.txt"), "либо 0, либо 1" ("?"). По умолчанию квантификатор для данного набора символов равен единице ("document[0-9]\.txt").

Разумеется, для более гибкого поиска сочетаний эти связки "набор символов - квантификатор" можно объединять в метаструктуры.

Пользуйтесь функциями регулярных выражений только если вы не знаете точно, какая "там" строка. Из примеров: поисковый код этого сайта, в котором из строки поиска вырезаются служебные символы и короткие слова а так же вырезаются лишние пробелы (вернее, все пробелы сжимаются: " +" заменяется на один пробел). При помощи этих функций я проверяю email пользователя, оставляющего свой отзыв. Много полезного можно сделать, но важно иметь в виду: регулярные выражения не всесильны. Например, сложную замену в большом тексте ими лучше не делать. Ведь, к примеру, комбинация "(.*)" в программном плане означает перебор всех символов текста. А если шаблон не привязан к началу или концу строки, то и сам шаблон "двигается" программой через весь текст, и получается двойной перебор, вернее перебор в квадрате. Нетрудно догадаться, что еще одна комбинация "(.*)" означает перебор в кубе, и так далее. Возведите в третью степень, скажем, 5 килобайт текста. Получается 125 000 000 000 (прописью: сто двадц пять миллиардов операций). Конечно же, если подходить строго, там стольких операций не будет, а будет раза в четыре-восемь меньше, но важен сам порядок цифр.

usman
25.02.2009, 12:49
Зачем же такие сложности, спросите вы? И будете правы, так как все это не нужно в том объеме, в котором я описал. Чаще всего вы будете использовать достаточно простые конструкции.

Давайте посмотрим, как можно создать шаблон в виде регулярного выражения на примере живого сайта. Ссылку на него я давать не буду, просто покажу, какой HTML код у него внутри.

Открываем страничку со статьей и смотрим ее исходный код. Находим место, где начинается статья, и видим вот такой код:



<tr><td colspan="3">
<div class="txt" style="margin:10px 0 20px 0;">
<div id="hypercontext"><index>
<div id='news-id-86'>Если вдруг
....
</div>
</index> </div>
<SCRIPT type="text/javascript">
Как видите, в данном случае все понятно с первого взгляда: текст начинается после тега <div id='news-id-86'> и заканчивается перед </div></index>. Если посмотреть другие статьи с этого же сайта, то мы увидим, что в них текст начинается после похожего дива, только ньюс-айди там будет другой. Конечно, мы не сможем указать все возможные варианты идентификаторов статей обычным способом, но нам на помощь придет регулярное выражение.

Шаблон для начального тега можно задать следующим образом:
<div id='news-id-\d+'>где \d+ обозначает "одна или более цифр". Таким образом мы охватим все возможные значения идентификаторов статей.

Шаблон для конечного тега можно задать так:
</div>\s*</index>где \s* обозначает "ноль или более пробельных символов". Пробельными символяами являются символы пробела, первода строки и возврата каретки и табуляция. В нашем случае этот квантификатор нужен, так как у нас есть перевод каретки перед закрывающим индексом.

В результате наше регулярное выражение будет выглядеть так:

<div id='news-id-\d+'>(.+)</div>\s*</index>