Общие сведения

Синтакcис шаблонов, используемых в функциях регулярных выражений, во многом похож на синтаксис, используемый в Perl. Выражение должно быть заключено в ограничители, например, прямые слеши '/'. Ограничителем могут выступать произвольные символы, кроме буквенно-цифровых и обратного слеша '\'. Если ограничительный символ встречается в шаблоне, его необходимо экранировать. Начиная с PHP 4.0.4 в качестве ограничителя доступны комбинации, используемые в Perl: (), {}, [] и <>. Подробней об этом рассказано в разделе Синтаксис регулярных выражений.

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

PHP также поддерживает POSIX-совместимые регулярные выражения, используя соответствующий модуль.

Требования

Поддержка Perl-совместимых регулярных выражений реализована в соответствующей PCRE библиотеке, которая распространяется с открытым исходным кодом. Автором библиотеки является Philip Hazel, авторские права принадлежат кембриджскому университету, Англия. Исходный код доступен по ссылке ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/.

Необходимо учитывать некоторые ограничения PCRE. http://www.pcre.org/pcre.txt для получения более полной информации.

Установка

Начиная с PHP 4.2.0, Perl-совместисмые регулярные выражения (PCRE) доступны по умолчанию. Вы можете отключить их при помощи --without-pcre-regex. В случае, если вы хотите использовать библиотеку, отличную от идущей в стандартной поставке РНР, используйте опцию --with-pcre-regex=DIR для указания директории, содержащей необходимые файлы. Если у вас версия PHP менее, чем 4.2.0, вам необходимо сконфигурировать и пересобрать PHP с опцией --with-pcre-regex[=DIR], чтобы включить поддержку PCRE-функций.

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

Настройка во время выполнения

Данное расширение не определяет никакие директивы конфигурации в php.ini.

Типы ресурсов
Данное расширение не определяет никакие типы ресурсов.

Предопределенные константы

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

Таблица 1. PREG константы

константаописание
PREG_PATTERN_ORDERМеняет порядок элементов в результирующем массиве так, чтобы элемент $matches[0] содержал полные вхождения шаблона, элемент $matches[1] - все вхождения первой взятой в круглые скобки подмаски, и так далее. Только reg_match_all() реагирует на данный модификатор; остальными функциями он игнорируется.
PREG_SET_ORDERМеняет порядок элементов в результирующем массиве так, чтобы элемент $matches[0] содержал первый набор вхождений (полное вхождение, вхождение первой подмаски, заключенной в круглые скобки...), аналогично элемент $matches[1] - второй набор вхождений, и так далее. Только reg_match_all() реагирует на данный модификатор; остальными функциями он игнорируется.
PREG_OFFSET_CAPTUREСмотрите описание флагаPREG_SPLIT_OFFSET_CAPTUREДанный флаг доступен в PHP 4.3.0 и выше.
PREG_SPLIT_NO_EMPTYВ случае, если этот флаг указан, функция preg_split()вернет только непустые подстроки.
PREG_SPLIT_DELIM_CAPTUREВ случае, если этот флаг указан, выражение, заключенное в круглые скобки в разделяющем шаблоне, также извлекается из заданной строки и возвращается функцией. Этот флаг был добавлен в PHP 4.0.5.
PREG_SPLIT_OFFSET_CAPTUREВ случае, если этот флаг указан, для каждой найденной подстроки будет указана ее позиция в исходной строке. Необходимо помнить, что этот флаг меняет формат возвращаемых данных: каждое вхождение возвращается в виде массива, в нулевом элементе которого содержится найденная подстрока, а в первом - смещение. Этот флаг доступен в PHP 4.3.0 и выше и используется только в функции preg_split().

Примеры правильных и неправильных шаблонов

Примеры правильных шаблонов

/<\/\w+>/
|(\d{3})-\d+|Sm
/^(?i)php[34]/
{^\s+(\s+)?$}

Примеры неправильных шаблонов

/href='(.*)' - пропущен закрывающий ограничитель
/\w+\s*\w+/J - неизвестный модификатор 'J'
1-\d3-\d3-\d4| - пропущен открывающий ограничитель

Модификаторы шаблонов

Ниже перечислены все доступные на сегодняшний день модификаторы. Имя, взятое в круглые скобки, указывает внутреннее PCRE имя для данного модификатора.

i (PCRE_CASELESS)

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

m (PCRE_MULTILINE)

По умолчанию PCRE обрабатывает данные как однострочную символьную строку (даже если она содержит разделители строк). Метасимвол начала строки '^' соответствует только началу обрабатываемого текста, в то время как метасимвол "конец строки" '$' соответствует концу текста, либо позиции перед завершающим текст переводом строки (в случае, если модификатор D не установлен). В Perl ситуация полностью аналогична.

Если этот модификатор используется, метасимволы "начало строки" и "конец строки" также соответствуют позициям перед произвольным символом перевода и строки и, соответственно, после. Это соответствует Perl-модификатору \m. В случае, если обрабатываемый текст не содержит символов перевода строки, либо шаблон не содержит метасимволов '^' или '$', данный модификатор не имеет никакого эффекта.

s (PCRE_DOTALL)

Если данный модификатор используется, метасимвол "точка" в шаблоне соответствует всем символам, включая перевод строк. Без него - всем, за исключением переводов строк. Этот модификатор эквивалентен записи /s в Perl. Класс символов, построенный на отрицании, например [^a], всегда соответствует переводу строки, независимо от наличия этого модификатора.

x (PCRE_EXTENDED)

Если данный модификатор используется, неэкранированные пробелы, символы табуляции и пустой строки в шаблоне игнорируются, если они не являются частью символьного класса. Также игнорируются все символы между неэкранированным символом '#' (если он не является частью символьного класса) и символом перевода строки (включая сами символы '\n' и '#'). Это эквивалентно Perl-модификатору \x, и позволяет размещать комментарий в сложных шаблонах. Замечание: это касается только символьных данных. Пробельные символы не фигурируют в служебных символьных последовательностях, к примеру, в последовательности '(?(', открывающей условную подмаску.

e

Если данный модификатор используется, preg_replace() после выполнения стандартных подстановок в заменяемой строке интерпретирует ее как PHP-код и использует результат для замены искомой строки.

Только preg_replace() реагирует на данный модификатор; остальными функциями он игнорируется.

Замечание: Этот модификатор недоступен в PHP 3.

A (PCRE_ANCHORED)

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

D (PCRE_DOLLAR_ENDONLY)

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

S

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

U (PCRE_UNGREEDY)

Этот модификатор инвертирует жадность квантификаторов, таким образом они по умолчанию не жадные. Но становятся жадными, если за ними следует символ '?'. Такая возможность не совместима с Perl. Модификатор U также может использоваться внутри шаблона, при помощи '?U' записи.

X (PCRE_EXTRA)

Этот модификатор включает дополнительную функциональность PCRE, которая не совместима с Perl: любой обратный слеш в шаблоне, за которым следует символ, не имеющий специального значения, приводят к ошибке. Это обусловлено тем, что подобные комбинации зарезервированы для дальнейшего развития. По умолчанию же, как и в Perl, слеш со следующим за ним символом без специального значения трактуется как as опечатка. На сегодняшний день это все возможности, которые управляются данным модификатором

u (PCRE_UTF8)

Этот модификатор включает дополнительную функциональность PCRE, которая не совместима с Perl: шаблоны обрабатываются как UTF8 строки. Модификатор u доступен в PHP 4.1.0 и выше для Unix-платформ, и в PHP 4.2.3 и выше для Windows платформ.

Отличия от PERL

Библиотека PCRE является набором функций, которые реализуют поиск по шаблону, используя синтаксис, подобный синтаксису Perl 5 с небольшими отличиями. Текущая реализация соответствует версии Perl 5.005.

Отличия от Perl

Разница описана относительно версии Perl 5.005.

1. По умолчанию пробельными символами являются все символы, распознаваемые библиотечной функцией языка Си isspace(). Это позволяет собрать PCRE библиотеку с произвольными символьными наборами. В стандартной поставке функция isspace() определяет как пробельные следующие символы: пробел, разрыв страницы, начло строки, перевод каретки, горизонтальную и вертикальную табуляцию. Начиная с версии Perl 5.002, символ вертикальной табуляции \v не является пробельным и, соответственно, не соответствует классу символов \s.

2. PCRE не позволяет использовать квантификаторы повторения в условных выражениях. Perl позволяет это делать, но получаемый результат может существенно отличаться от ожидаемого. Например, (?!a){3} не означает, что три следующих символа будут не 'a'. Он всего лишь трижды утверждает, что следующий символ не 'a'.

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

4. Несмотря на то, что символ, соответствующий ASCII-коду 0 (бинарный ноль), допускается в обрабатываемом тексте, он недопустим в шаблоне (так как передается в качестве аргумента Си-функции как нормальная строка, завершаемая нулевым символом). Cледующая служебная последовательность "\\x00" может быть использована для представления бинарного ноля.

5. Следующие служебные последовательности, используемые в Perl, не поддерживаются: \l, \u, \L, \U, \E, \Q. Это связано с тем, что обработка указанных последовательностей производится внутренним Perl-механизмом обработки строк и не является частью механизма регулярных выражений.

6. Perl модификатор \G не поддерживается, так как он не входит в рамки простого сопоставления шаблону.

7. Достаточно очевидно, что PCRE не поддерживает конструкции вида (?{code}).

8. Теперь немного о чудаковатости в Perl 5.005_02, связанной с фиксацией результата в случае, когда часть шаблона повторяется. Например, применяя шаблон /^(a(b)?)+$/ к строке "aba", переменная $2 соответствует 'b'. Но при применении шаблона /^(aa(bb)?)+$/ к строке "aabbaa" переменная $2 оказывается неустановленной. А в случае, если шаблон изменить на /^(aa(b(b))?)+$/, переменные $2 и $3 окажутся установленными. В Perl 5.004, в обоих случаях переменная $2 будет содержать соответствующее значение, что соответствует PCRE. Если в будущем Perl изменит поведение в данной ситуации, PCRE также может измениться.

9. Еще одна несовместимость, не находящая разумного объяснения. Шаблон /^(a)?(?(1)a|b)+$/ соответствует строке 'a' в PERL, но не в PCRE. В то же время шаблон /^(a)?a/ соответствует строке 'a' и в Perl и в PCRE, оставляя переменную $1 неустановленной.

10. PCRE также предоставляет некоторое расширение возможностей Perl для обработки регулярных выражений:

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

10.2 В случае, если модификатор PCRE_DOLLAR_ENDONLY используется и PCRE_MULTILINE не используется, специальный символ '$' соответствует исключительно концу обрабатываемых данных.

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

10.4 Модификатор PCRE_UNGREEDY инвертирует жадность квантификаторов, таким образом они по умолчанию не жадные. Но становятся жадными, если за ними следует символ '?'.

Повторение

Повторение задается при помощи квантификаторов, следующих за любым из указанных ниже элементов:

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

Общий квантификатор повторения указывает минимальное и максимальное допустимое количество совпадений, согласно двум числам, заключенными в фигурные скобки и разделенными запятой. Числа должны быть меньше чем 65536, и первое число не должно превышать второе по значению. Например: z{2,4} соответствует "zz", "zzz" или "zzzz". Закрывающая фигурная скобка сама по себе не является специальным символом. В случае, если второе число опущено, но запятая присутствует, нет верхнего предела; в случае, если и второе число и запятая опущены, требуется точное число повторений. Таким образом [aeiou]{3,} соответствует как минимум трем последовательным гласным (а также любому их количеству выше трех), в то время как \d{8} соответствует исключительно восми цифрами. Открывающая фигурная скобка, расположенная в недопустимой для квантификатора позиции, либо не соответствующая синтаксису квантификатора, интерпретируется как обыкновенная символьная строка. Например, {,6} не является квантификатором, а интерпретируется как символьная строка из четырех символов.

Квантификатор {0} является допустимым и ведет себя таким образом, будто бы сам квантификатор и предшествующий ему элемент отсутствуют.

Для удобства (а так же обратной совместимости) три наиболее распространённых квантификатора имеют односимвольные аббревиатуры:

Таблица 2. Односимвольные квантификаторы

* эквивалентен {0,}
+ эквивалентен {1,}
? эквивалентен {0,1}

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

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

По умолчанию, все квантификаторы являются "жадными", это означает, что они совпадают максимально возможное количество раз (но не более, чем максимально допустимое количество раз), не приводя к невозможности сопоставления остальных частей шаблона. Классический пример проблем, которые могут возникнуть в связи с такой особенностью квантификаторов - нахождение комментариев в C-программах. Комментарием считается произвольный текст, находящийся внутри символьных комбинаций /* и */ (при этом, символы '/' и '*' также могут быть частью комментария). Попытка найти комментарии при помощи шаблона /\*.*\*/ в строке /* первый комментарий */ не комментарий /* второй комментарий */ закончится неудачей, поскольку указанный шаблон соответствует всей строке целиком (из-за жадности кватификатора '*').

Однако, если сразу же после квантификатора идет вопросительный знак, он перестает быть жадным и соответствует минимально допустимому количеству раз. Таким образом, шаблон /\*.*?\*/ корректно находит все комментарии языка Си. Использование символа '?' после квантификатора влияет исключительно на его жадность, и не затрагивает никакие другие свойства. Не следует путать использование символа '?' как, собственно, квантификатора (ноль либо одно соответствие) и как ограничителя жадности. Также в следствие его двойственной функциональности может использоваться следующая запись: \d??\d, которая в первую очередь соответствует одной цифре, но также может соответствовать и двум цифрам, если это необходимо для соответствия остальных частей шаблона.

В случае, если установлена опция PCRE_UNGREEDY (отсутствующая в Perl), квантификаторы являются не жадными по умолчанию, но могут становиться жадными, если за ними следует символ '?'. Говоря другими словами, знак вопроса инвертирует жадность квантификаторов.

В случае, если используется подмаска с квантификатором, для которого задано минимальное количество повторений (больше одного), либо если задано максимальное количество повторений, для откомпилированного шаблона требуется больше памяти (пропорционально миниму либо максимуму соответственно).
В случае, если шаблон начинается с .* либо .{0,}, и установлен модификатор PCRE_DOTALL (являющийся аналогом Perl-опции /s), который позволяет метасимволу "точка" соответствовать переводу строки, шаблон неявно заякоривается. Это происходит поскольку все последующие конструкции будут сопоставляться с каждой символьной позицией в обрабатываемом тексте, и, как следствие, начало строки - единственная позиция, дающая наиболее полное совпадение. PCRE рассматривает каждый такой шаблон, как если бы ему предшествовала последовательность \A. В случае, если известно, что данные не содержат переводов строк, а сам шаблон начинается на .*, рекомендуется использовать PCRE_DOTALL для оптимизации шаблона, либо использовать метасимвол '^' для указания явного заякоривания.
В случае, если захватывающая подмаска повторяется, результирующим значением подмаски будет подстрока, совпадающая с результатом последней итерации. Например, после того, как (tweedle[dume]{3}\s*)+ совпадет с "tweedledum tweedledee", результирующим значением подмаски будет "tweedledee". Однако, если присутствуют вложенные захватывающие подмаски, соответствующие значения могут быть установлены в предыдущих итерациях. Например, после того, как /(a|(b))+/ совпадет с "aba", значением второй захваченной подстроки будет "b".

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

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

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

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

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

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

Утверждения

Утверждения - это проверки касательно символов, идущих до или после текущей позиции сопоставления, ничего при этом не поглощая (никакие символы исходного текста не ставятся в соответствие утверждениям). Наиболее простые варианты утверждений, такие как \b, \B, \A, \Z, \z, ^ и $ были рассмотрены ранее. Более сложные утверждения записываются как подмаски. Утверждения бывают двух видов: те, которые анализируют текст, предшествующий текущей позиции, и идущий после нее.

Сопоставление подмаски, содержащий утверждение, происходит обычным образом, за исключением того, что текущая позиция не изменяется. Утверждения касательно последующего текста начинаются с (?= для положительных утверждений и с (?! для отрицающих утверждений. Например, \w+(?=;) совпадает со словом, за которым следует символ ';', но при этом сама точка с запятой в совпадение не включается. А foo(?!bar) соответствует любому появлению "foo", после которого не идёт "bar". Заметим, что похожий шаблон (?!foo)bar не будет искать вхождение "bar", которому предшествует любая строка за исключением "foo". Но, тем не менее, он будет соответствовать любым вхождениям подстроки "bar", поскольку условие (?!foo) всегда TRUE, если следующие три символа - "bar". Для получения желаемого результата необходимо воспользоваться второй категорией утверждений.

Утверждения касательно предшествующего текста начинаются с (?<= для положительных утверждений и (?<! для отрицающих. Например, (?<!foo)bar не найдёт вхождения "bar", которым не предшествует "foo". Сами утверждения 'назад' ограничены так, чтобы все подстроки, которым они соответствуют, имели фиксированную длину. Но, в случае, если используются несколько альтернатив, они не обязаны иметь одинаковую длину. Таким образом шаблон (?<=bullock|donkey) корректен, но (?<!dogs?|cats?) вызовет ошибку во время компиляции. Ветки, которые соответствуют строкам разной длины, разрешены только на верхнем уровне утверждений касательно предшествующего текста. Это расширение относительно Perl 5.005, который требует чтобы все ветки соответствовали строкам одинаковой длины. Такое утверждение как (?<=ab(c|de)) не корректно, поскольку верхний уровень маски может соответствовать строкам разной длины, но его можно преобразовать к корректному шаблону, используя альтернативы на верхнем уровне: (?<=abc|abde). Утверждения касательно предшествующего текста реализованы так, что для каждой альтернативы текущая позиция временно переносится назад, на фиксированную ширину, после чего выполняется поиск соответствия условию. В случае, если перед текущей позицией недостаточно символов, поиск соответствия терпит неудачу. Утверждения назад в сочетании с однократными подмасками могут быть особенно удобны для поиска в конце строки; соответствующий пример приведен в конце раздела "Однократные подмаски".

Несколько утверждений (разных типов) могут присутствовать в утверждении, например: (?<=\d{3})(?<!999)foo совпадает с подстрокой "foo", которой предшествуют три цифры, отличные от "999". Следует понимать, что каждое из утвержений проверяется относительно одной и той же позиции в обрабатываемом тексте. Вначале выполняется проверка того, что предшествующие три символа - это цифры, затем проверяется, чтобы эти же цифры не являлись числом 999. Приведенный выше шаблон не соответствует подстроке "foo", которой предшествуют шесть символов, первые три из которых - цифры, а последние три не образуют "999". Например, он не соответствует строке "123abcfoo", в то время как шаблон (?<=\d{3}...)(?<!999)foo - соответствует. В этом случае анализируются предшествующие шесть символов на предмет того, чтобы первые три из них были цифрами, а последние три не образовали "999".

Утверждения могут быть вложенными, причем в произвольных сочетаниях: (?<=(?<!foo)bar)baz соответствует подстроке "baz", которой предшествует "bar", перед которой, в свою очередь, нет "foo", а (?<=\d{3}(?!999)...)foo - совершенно другой шаблон, соответствующий подстроке "foo", которой предшествуют три цифры и три произвольных символа, отличных от "999".

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

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

Однократные подмаски

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

В качестве примера, рассмотрим шаблон \d+foo в применении к строке 123456bar

После того, как \d+ будет сопоставлен с первыми шестью цифрами, сопоставление "foo" потерпит неудачу. После этого, в соответствие \d+, будет сопоставлено 5 цифр, после очередной неудачи будет сопоставлено 4 цифры и так далее. В конце концов весь шаблон потерпит неудачу. Однократные подмаски указывают, что если одна часть шаблона была сопоставлена, ее не стоит анализировать повторно. Применимо к приведенному выше примеру весь шаблон потерпел бы неудачу после первого же неудачного сопоставления с "foo". Записываются однократные шаблоны при помощи круглых скобок следующим образом: (?>. Например: (?>\d+)bar

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

Говоря другими словами, подмаски такого типа соответствуют той части подстроки, которой соответствовала бы одиночная изолированная маска, заякоренная на текущей позиции обрабатываемого текста.

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

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

Однократные подмаски могут использоваться совместно с утверждениями касательно предшествующего текста для описания эффективных сопоставлений в конце обрабатываемого текста. Рассмотрим простой шаблон abcd$ в применении к длинному тексту, который не соответствует указанной маске. Поскольку поиск происходит слева направо, вначале PCRE будет искать букву "a", и только потом анализировать следующие записи в шаблоне. В случае, если шаблон указан в виде ^.*abcd$. В таком случае вначале .* сопоставляется со всей строкой, после чего сопоставление терпит неудачу (так как нет последующего символа 'a'). После чего .* сопоставляется со всей строкой, кроме последнего символа, потом кроме двух последних символов, и так далее. В конечном итоге поиск символа 'a' происходит по всей строке. Однако, если шаблон записать в виде: ^(?>.*)(?<=abcd) повторный анализ для .* не выполняется, и, как следствие, может соответствовать только всей строке целиком. После чего утверждение проверяет последние четыре символа на совпадение с 'abcd', и в случае неудачи все сопоставление терпит неудачу. Для больших объемов обрабатываемого текста этот подход имеет значительный выигрыш во времени выполнения.

Если шаблон содержит неограниченное повторение внутри подмаски, которая в свою очередь также может повторяться неограниченное количество раз, использование однократных подмасок позволяет избегать многократных неудачных сопоставлений, которые длятся достаточно продолжительное время. Шаблон (\D+|<\d+>)*[!?] соответствует неограниченному количеству подстрок, которые состоят не из цифр, либо из цифр заключенных в <>, за которыми следует ? либо !. В случае, если в обрабатываемом тексте содержатся соответствия, время работы регулярного выражения будет невелико. Но если его применить к строке aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa это займет длительное время. Это связанно с тем, что строка может быть разделена между двумя частями шаблона многими способами, и все они будут опробованы (в примере мы использовали [?!], поскольку в случае одиночного символа в конце шаблона и PCRE и Perl выполняют оптимизацию. Они запоминают последний одиночный символ и в случае его отсутствия выдают неудачу). Если изменить шаблон на ((?>\D+)|<\d+>)*[!?], нецифровые последовательности не могут быть разорваны, и невозможность сопоставления обнаруживается гораздо быстрее.

Условные подмаски

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

(?(condition)yes-pattern)(?(condition)yes-pattern|no-pattern)

В случае успешного сопоставления условия condition, используется подмаска yes-pattern, в противном случае no-pattern (если он присутствует). Если указано более двух альтернатив, возникнет ошибка во время компиляции.

Условия бывают двух видов. В случае, если между скобками заключены цифры, условие будет выполняться в том случае, если подмаска с соответствующим номером была успешно сопоставлена. Рассмотрим следующий шаблон (он содержит незначащий пробел для удобства чтения, подразумевается использование модификатора PCRE_EXTENDED), разделив его для удобства на три смысловые части: ( \( )? [^()]+ (?(1) \) )

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

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

(?(?=[^a-z]*[a-z])\d{2}-[a-z]{3}-\d{2}|\d{2}-\d{2}-\d{2} )

Приведен пример с утверждающим условием касательно предшествующего текста, которое выполняется для необязательной последовательности не-букв с последующей буквой. Говоря другими словами, указанное условие проверяет наличие хотя бы одной предшествующей буквы. В случае, если буква найдена, выполняется сопоставление с первой альтернативой, в противном случае - со второй альтернативой. Приведенный шаблон соответствует строкам двух видов: dd-aaa-dd либо dd-dd-dd, где aaaa - это буквы, а dd - цифры.

Комментарии

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

В случае, если используется модификатор PCRE_EXTENDED, неэкранированный символ '#' вне символьного класса также означает начало блока комментария, который длится до конца текущей строки.

Рекурсивные шаблоны

Рассмотрим задачу поиска соответствия со строкой, находящихся внутри неограниченного количества круглых скобок. Без использования рекурсии лучшее, что можно сделать - написать шаблон, который будет решать задачу для некоторой ограниченной глубины вложенности, так как обработать неограниченную глубину не предоставляется возможным. В Perl 5.6 предоставлены некоторые экспериментальные возможности, которые в том числе позвояляют реализовать рекурсию в шаблонах. Специально обозначение (?R) используется для указания рекурсивной подмаски. Таким образом, приведем PCRE шаблон, решающий поставленную задачу (подразумевается, что используется модификатор PCRE_EXTENDED, незначащие пробелы игнорируются): \( ( (?>[^()]+) | (?R) )* \)

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

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

Значение, устанавливаемое для захватывающей подмаски будет соответствовать значению, захваченному на наиболее глубоком уровне рекурсии. В случае, если приведенный выше шаблон сопоставляется со строкой (ab(cd)ef), захваченным значением будет 'ef', которое является последним значением, принимаемым на верхнем уровне. В случае, если добавить дополнительные скобки \( ( ( (?>[^()]+) | (?R) )* ) \), захваченным значением будет "ab(cd)ef". В случае, если в шаблоне встречается более, чем 15 захватывающих скобок, PCRE требуется больше памяти для обработки рекурсии, чем обычно. Память выделяется при помощи функции pcre_malloc, и освобождается соответственно функцией pcre_free. Если память не может быть выделена, сохраняются данные только для первых 15 захватывающих скобок, так как нет способа выдать ошибку out-of-memory изнутри рекурсии.

Производительность

Некотрые элементы, которые могут встречаться в шаблонах, являются более эффективными, чем ряд других. Например, гораздо эффективней использовать символьный класс [aeiou] вместо набора альтернатив (a|e|i|o|u). Как правило, более простая конструкция является более эффективной. Книга Jeffrey Friedl'а содержит много обсуждений вопроса оптимизации регулярных выражений.

В случае, если шаблон начинается с .* и используется флаг PCRE_DOTALL, шаблон неявно заякоривается, так как он может совпадать только в начале строки. Но если PCRE_DOTALL не используется, PCRE не может выполнить соответствующую оптимизацию, так как в таком случае метасимвол '.' не соответствует символу начала строки (если обрабатываемые данные содержат переводы строк, такой шаблон может соответствовать шаблону не от начала строки, а от позиции непосредственно после перевода строки). Например, применяя шаблон (.*) second к строке "first\nand second" (где \n обозначает символ перевода строки), значение, захваченное первой подмаской, будет 'and'. Чтобы обработать все возможные точки соответствия, PCRE пытается сопоставить шаблон после каждого символа перевода строки.

В случае, если вы используете подобные шаблоны для обработки данных, не содержащих переводы строк, для лучшей производительности используйте модификатор PCRE_DOTALL, либо начинайте шаблон с ^.* для указания явного заякоривания. Это предотвратит PСRE от поиска символов новых строк и дополнительных попыток сопоставить шаблон с каждой такой найденной позицией.

Избегайте шаблонов, которые содержат вложенные неограниченные повторения. Сопоставление их со строками, не содержащими совпадений, занимает длительное время. Рассмотрим пример шаблона (a+)*

Он может соответствовать с "aaaa" 33-мя различными способами, и эта цифра очень быстро растет при увеличении строки. (В данном примере, квантификатор * может совпадать 0, 1, 2, 3 или 4 раза, и для каждого такого случая, кроме нуля, квантификатор + также может совпадать различное число раз.) Если остаток шаблона таков, что все совпадение терпит неуачу, PCRE должно попробовать все возможные варианты совпадения, что может потребовать огромного количества времени.

При помощи оптимизации можно отловить наиболее простые случаи, такие как (a+)*b где следом идёт литеральный символ. Прежде, чем производить стандартную процедуру поиска, PCRE проверяет в последующей подстроке наличие символа 'b', и, в случае отсутствия такового, попытка сопоставления немедленно завершается неудачей. Однако, когда последующего литерала нет, оптимизация не может быть применена. Вы можете ощутить разницу, сравнив поведение (a+)*\d с поведением приведенного выше шаблона. Первый определяет невозможность сопоставления практически сразу же, при сопоставлении со строкой состоящей из символов 'a', в то время как второй тратит длительное время на поиск в строках длинее 20 символов.

Определение регулярного выражения

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

Большая часть символов сохраняет свое значение в шаблоне и означает совпадение с соответствующим символом. Банальный пример: шаблон The quick brown fox соответствует той части строки, которая идентична приведенной фразе.

Метасимволы

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

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

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

^ декларирует начало данных (или линии, в многострочном режиме)

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

.(точка) соответствует любому символу, кроме перевода строки (по умолчанию)

[ начало описания символьного класса

] конец описания символьного класса

| начало ветки условного выбора

( Начало подмаски

) конец подмаски

? расширяет смысл метасимвола '(' , квантификатор, означающий ноль либо одно вхождение, квантификатор жадности

* квантификатор, означающий ноль или более вхождений

+ квантификатор, означающий одно или более вхождений

{ начало количественного квантификатора

} конец количественного квантификатора

Часть шаблона, заключенная в квадратные скобки, называется символьным классом. Внутри символьных классов используются следующие метасимволы:

\ общий экранирующий символ

^ означает отрицание класса, допустим только в начале класса

- означает символьный интервал

] завершает символьный класс

Обратный слэш

Символ '\' имеет несколько применений. Прежде всего, если он предшествует не буквенно-цифровому символу, он снимает с него специальное значение. Применение обратного слеша как экранирующего символа допустимо как в символьном классе, так и вне него.

Например, если вы хотите задать соответствие символу '*', в шаблоне вам необходимо указать '\*'. Это предотвратит трактование '*' как метасимвола с особым значением. Во избежание ошибок всегда экранируйте не буквенно-цифровые символы, если хотите указать соответствие самому символу. В частном случае для сопоставления с самим символом обратного слеша, используйте запись '\\'.

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

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

\a символ оповещения, сигна, (шестнадцатиричный код 07)
\cx "Ctrl+x", где x - произвольный символ
\e escape (шестнадцатеричный код 1B)
\f разрыв страницы (шестнадцатиричный код 0C)
\n перевод строки (шестнадцатиричный код 0A)
\r возврат каретки (шестнадцатиричный код 0D)
\t табуляция (шестнадцатиричный код 09)
\xhh символ с шестнадцатиричным кодом hh
\ddd символ с восьмеричным кодом либо ссылка на подмаску

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

После "\x" считываются еще две шестнадцатиричные цифры (они могут быть записаны в нижнем регистре).

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

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

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

\040 еще один способ записи пробела
\40 то же самое в случае, если данной записи предшествует менее сорока подмасок
\7 всегда интерпретируется как ссылка на подмаску
\11 может быть как обратной ссылкой, так и альтернативной записью символа табуляции
\011 всегда интерпретируется как символ табуляции
\0113 символ табуляции, за которым следует цифра "3"
\113 интерпретируется как символ с восьмеричным кодом 113 (так как ссылок на подмаски не может быть более чем 99)
\377 байт, всецело состоящий из единичных битов
\81 либо обратная ссылка, либо бинарный ноль, за которым следуют цифры "8" и "1"

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

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

Третье использование обратного слеша - указание общего типа символов:

\d любая десятичная цифра
\D любой символ, кроме десятичной цифры
\s любой пробельный символ
\S любой непробельный символ
\w Любой символ, образующий "слово"
\W Любой символ, не образующий "слово"

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

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

Описанные выше типы символов могут применяться как внутри, так и вне символьных классов, и соответствуют одному символу данного типа.

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

\b граница слова
\B не является границей слова
\A начало данных (независимо от многострочного режима)
\Z конец данных либо позиция перед последним символом строки, в случае если это символ перевода строки (независимо от многострочного режима)
\z конец данных (независимо от многострочного режима)

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

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

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

Метасимволы начала и конца строки

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

Метасимвол ^ не обязан быть первым символом строки в случае, если в шаблоне используются несколько альтернатив, но должен быть первым символом в каждой из альтернатив, в которой он встречается, если шаблон когда-либо сопоставим с соответствующей веткой. Если все альтернативы начинаются с метасимвола начала строки, то шаблон ограничен для совпадения исключительно в начале строки, говорят что шаблон "заякорен". (Существуют и другие способы "заякорить" шаблон).

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

Поведение метасимвола конца строки может быть изменено при помощи модификатора PCRE_DOLLAR_ENDONLY так, чтобы он соответствовал исключительно концу строки. Данный флаг никак не касается специальной последовательности \Z.

Значение метасимволов начала и конца строки меняется в случае, если модификатор PCRE_MULTILINE используется. В таком случае, помимо совпадений в начале либо конце строки, метасимволы ^ и $ соответствуют позиции непосредственно после символа перевода строки соответственно. Например, шаблон /^abc$/ встречается в строке def\nabc" в многострочном режиме и не встречается в нормальном режиме. Таким образом, шаблон который "заякорен" в однострочном режиме, не будет являться "заякоренным" в многострочном режиме. Модификатор PCRE_DOLLAR_ENDONLY игнорируется в случае, если модификатор PCRE_MULTILINE установлен.

Следует заметить, что служебные последовательности \A, \Z и \z могут использоваться для сопоставления с началом либо концом строки в обоих режимах. И если все ветви шаблона начинаются с \A, шаблон будет заякорен независимо от присутствия модификатора PCRE_MULTILINE.

Метасимвол точка

Вне символьного класса символ точка соответствует любому (в том числе и непечатному, бинарному) символу, кроме символа перевода строки '\n'. В случае, если модификатор PCRE_DOTALL используется, точка соответствует также символу перевода строки. Обработка метасимвола "точка", никак не связана с метасимволами начала и конца строки, единственное, что у них общего,- так это специальное отношение к символу перевода строки. Внутри символьного класса точка не имеет специального значения.

Квадратные скобки

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

Символьный класс соответствует одиночному символу обрабатываемой строки, причем сам символ должен содержаться в наборе, определяемым классом. В случае, если первым символом описания класса является ^, логика работы инвертируется: класс соответствует одиночному символу, который не содержится в наборе, определяемым классом. Если символ ^ необходим как член класса, его не следует помещать первым символом в описании класса либо необходимо экранировать при помощи обратного слеша.

К примеру, символьный класс [aeiou] соответствует любой гласной букве в нижнем регистре, в то время, как [^aeiou] соответствует любому символу, не являющемуся гласной буквой нижнего регистра. Следует понимать, что символ ^ всего лишь удобный инструмент для описания символов, не используемых в сопоставлении.

В случае, если производится регистронезависимое сопоставление, любая буква символьного класса соответствует как своему верхнему, так и нижнему регистру. Таким образом символьный класс [aeiou] соответствует как A, так и a. Аналогично, класс [^aeiou] не соответствует ни A, ни a.

Внутри символьного класса символ перевода строки "\n" не имеет специального значения, независимо от наличия модификаторов PCRE_DOTALL и PCRE_MULTILINE. Символьные классы, построенные на отрицании, например [^a], соответствуют символу перевода строки.

Символ минус - внутри класса используется для задания символьного диапазона. Например, [d-m] соответствует любому символу, находящемуся между d и m, включая сами символы d и m. В случае, если - необходим, как член класса, он должен находиться в такой позиции, в которой он не может интерпретироваться как диапазон (как правило, это первый и последний символ описания класса) либо экранироваться при помощи обратного слеша.

Недопустимо использовать закрывающую квадратную скобку в качестве границы символьного диапазона. К примеру шаблон [W-]46] будет интерпретирован как символьный класс, состоящий из двух символов ("W" и "-"), за которыми следует строка "46]", таким образом шаблон будет соответствовать строкам "W46]" или "-46]". Чтобы все же использовать символ ] в описании диапазона, его необходимо экранировать при помощи обратного слеша, к примеру шаблон [W-\]46] будет интерпретирован как символьный класс, состоящий из символьного диапазона вместе с двумя последующими символами 4 и 6. Такого же результата можно достичь используя шестнадцатиричное или восьмеричное представление символа ].

Для построения символьных диапазонов используется ASCII представление символов. Таким образом пограничные символы можно задавать непосредственно в числовом представлении, например, [\000-\037]. В случае, если выполняется регистронезависимый поиск, символы, описанные в диапазоне, также будут соответствовать символам обеих регистров. К примеру, диапазоны [W-c] и [][\^_`wxyzabc] эквивалентны (в случае регистронезависимого поиска). Например, если установлена локаль "fr" (Франция) необходимо использовать [\xc8-\xcb] для задания соответствия ударному E в обоих регистрах.

Общие типы символов \d, \D, \s, \S, \w, и \W также могут использоваться в символьных классах, добавляя при этом в класс те символы, которым соответствуют. Например, класс [\dABCDEF] соответствует любой шестнадцатиричной цифре. Символ ^ может использоваться совместно с общим типом, взятым в верхнем регисте, для указания более узкого набора символов. Например, класс [^\W_] соответствует любой букве или цифре, но не символу подчеркивания.

Все неалфавитные символы, кроме \, -, ^ (вначале) и завершающего ], не являются специальными символами, но использование экранирующего слеша перед ними не навредит.

Вертикальная черта

Символ вертикальной черты '|' используются для разделения альтернативных масок. Например шаблон gilbert|sullivan соответствует как "gilbert" так и "sullivan". Допустимо указывать любое количество альтернатив, также допустимо указывать пустые альтернативы (соответствуют пустой строке). В процессе поиска соответствия просматриваются все перечисленные альтернативы слева направо, останавливаясь после первого найденного соответствия. В случае, если альтернативные варианты перечислены в подшаблоне, то поиск соответствия означает нахождение соответствия одному из альтернативных вариантов подмаски и остатку основного шаблона.

Установка внутренних опций

Установки PCRE_CASELESS, PCRE_MULTILINE, PCRE_DOTALL и PCRE_EXTENDED могут быть локально предопределены в шаблоне с использованием специальных символьных Perl-последовательностей, заключенных между символами "(?" и ")".

Символы внутренних опций
i for PCRE_CASELESS
m для PCRE_MULTILINE
s для PCRE_DOTALL
x для PCRE_EXTENDED

Например, (?im) указывает на регистронезависимый, многострочный режим поиска. Также можно сбросить опцию, поставив перед ней символ '-', либо комбинировать установку и отмену режимов. Например, (?im-sx) устанавливает флаги PCRE_CASELESS, PCRE_MULTILINE и отменяет флаги PCRE_DOTALL и PCRE_EXTENDED. В случае, если опциональный символ расположен непосредственно после либо перед символом '-', опция будет отменена.

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

(?i)abc
a(?i)bc
ab(?i)c
abc(?i)

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

В случае, если опция встречается в подмаске, эффект может быть разным. В Perl 5.005 была добавлена следующая особенность: опция внутри подмаски влияет только на ту часть подмаски, которая идет после указания опции. Таким образом (a(?i)b)c соответствует исключительно строкам 'abc' и 'aBc' (предполагается, что модификатор PCRE_CASELESS не используется). Это означает, что cуществует возможность указывать различные наборы опций для отдельных участков шаблона. Применение опций в одной из альтернативных веток также распространяется на все последующие ветки. Например: (a(?i)b|c) соответствует "ab", "aB", "c" и "C", хотя при совпадении с "C" первая ветвь покидается до установки опции. Это объясняется тем, что установка всех опций происходит на этапе компиляции шаблона.

Опции, специфичные для PCRE, такие как PCRE_UNGREEDY и PCRE_EXTRA могут быть установлены точно так же, как и Perl-совместимые опции, путем использования символов U и X соответственно. Флаг (?X) специфичен тем, что должен быть расположен в шаблоне прежде, чем будет использоваться любая другая дополнительная возможность, даже если он расположен на верхнем уровне. Лучше всего размещать флаг (?X) в самом начале шаблона.
Подмаски

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

1. Локализирует набор альтернатив. Например, шаблон cat(aract|erpillar|) соответствует одному из слов "cat", "cataract" или "caterpillar". Без использования скобок он соответствовал бы строкам "cataract", "erpillar" или пустой строке.

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

Например, если строка "the red king" сопоставляется с шаблоном the ((red|white) (king|queen)), будут захвачены подстроки "red king", "red" и "king", и их номера соответственно 1, 2 и 3.

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

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

(?i:saturday|sunday)
(?:(?i)saturday|sunday)

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

preg_grep()

Возвращает массив вхождений, которые соответствуют шаблону
(PHP 4, PHP 5)

Описание

array preg_grep ( string pattern, array input [, int flags] )

preg_grep() возвращает массив, состоящий из элементов входящего массива input, которые соответствуют заданному шаблону pattern.

Параметр flags может принимать следующие значения:

PREG_GREP_INVERT

В случае, если этот флаг установлен, функция preg_grep(), возвращает те элементы массива, которые не соответствуют заданному шаблону pattern. Этот флаг доступен, начиная с PHP 4.2.0.

Начиная с PHP 4.0.4, результат, возвращаемый функцией preg_grep() использует те же индексы, что и массив исходных данных. Если такое поведение вам не подходит, примените array_values() к массиву, возвращаемому preg_grep() для реиндексации.

Пример

<?php
// Возвращает все элементы массива,
// содержащие числа с плавающей точкой$fl_array = preg_grep("/^(\d+)?\.\d+$/", $array);
?>

preg_last_error()

Возвращает код ошибки выполнения последнего PCRE

Описание

int preg_last_error ( void )

Возвращаемые значения

Возвращает одну из следующих констант:

PREG_NO_ERROR
PREG_INTERNAL_ERROR
PREG_BACKTRACK_LIMIT_ERROR (see also pcre.backtrack_limit)
PREG_RECURSION_LIMIT_ERROR (see also pcre.recursion_limit)
PREG_BAD_UTF8_ERROR

preg_match_all()

Выполняет глобальный поиск шаблона в строке (PHP 3 >= 3.0.9, PHP 4, PHP 5)

Описание

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] содержит массив вхождений первой подмаски, и так далее.

<?php 
preg_match_all("|<[^>]+>(.*)]+>|U","example:<div align=left>this is a test</div>",
$out, PREG_PATTERN_ORDER);
echo $out[0][0] . ", " . $out[0][1] . "\n";
echo $out[1][0] . ", " . $out[1][1] . "\n";
?>

Результат работы примера:

<b>example:</b>, <div align=left>this is a test</div>
example:, this is a test

Как мы видим, $out[0] содержит массив полных вхождений шаблона, а элемент $out[1] содержит массив подстрок, содержащихся в тегах.

PREG_SET_ORDER

Если этот флаг установлен, результат будет упорядочен следующим образом: элемент $matches[0] содержит первый набор вхождений, элемент $matches[1] содержит второй набор вхождений, и так далее.

<?php
preg_match_all("|<[^>]+>(.*)]+>|U","<b>example:<div align=\"left\">this is a test</div>",
$out,PREG_SET_ORDER);
echo $out[0][0] . ", " . $out[0][1] . "\n";
echo $out[1][0] . ", " . $out[1][1] . "\n";
?>

Результат работы примера:

<b>example:</b>, example:<div align="left">this is a test</div>, this is a test

В таком случае массив $matches[0] содержит первый набор вхождений, а именно: элемент $matches[0][0] содержит первое вхождение всего шаблона, элемент $matches[0][1] содержит первое вхождение первой подмаски, и так далее. Аналогично массив $matches[1] содержит второй набор вхождений, и так для каждого найденного набора.

PREG_OFFSET_CAPTURE

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

В случае, если никакой флаг не используется, по умолчанию используется PREG_PATTERN_ORDER.

Поиск осуществляется слева направо, с начала строки. Дополнительный параметр offset может быть использован для указания альтернативной начальной позиции для поиска. Дополнительный параметр offset доступен, начиная с PHP 4.3.3.

Замечание: Использование параметра offset не эквивалентно замене сопоставляемой строки выражением substr($subject, $offset) при вызове функции preg_match_all(), поскольку шаблон pattern может содержать такие условия как ^, $ или (?<=x). Вы можете найти соответствующие примеры в описании функции preg_match().

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

Пример. Получение всех телефонных номеров из текста.

<?phppreg_match_all("/\(?(\d{3})?\)?(?(1)[\-\s])\d{3}-\d{4}/x","Call 555-1212 or 1-800-555-1212", $phones);
?>

Пример. Жадный поиск совпадений с HTML-тэгами

<?php
// Запись \\2 является примером использования ссылок на подмаски.
// Она означает необходимость соответствия подстроки строке, зафиксированной
// второй подмаской, в нашем примере это ([\w]+).
// Дополнительный слеш необходим, так как используются двойные кавычки.
$html = "<b>bold text</b><a href=howdy.html>click me</a>";

preg_match_all("/(<([\w]+)[^>]*>)(.*)(<\/\\2>)/", $html, $matches);

for ($i=0; $i< count($matches[0]); $i++) {
echo "matched: " . $matches[0][$i] . "\n";
echo "part 1: " . $matches[1][$i] . "\n";
echo "part 2: " . $matches[3][$i] . "\n";
echo "part 3: " . $matches[4][$i] . "\n\n";
}
?>

Результат работы примера:

matched: <b>bold text</b>
part 1: <b>
part 2: bold textpart 3: </b>
matched: <a href=howdy.html>click me</a>
part 1: <a href=howdy.html>
part 2: click mepart 3: </a>

preg_match()

Выполняет проверку на соответствие регулярному выражению (PHP 3 >= 3.0.9, PHP 4, PHP 5)

Описание:

mixed preg_match ( string pattern, string subject [, array &matches [, int flags [, int offset]]] )

Ищет в заданном тексте subject совпадения с шаблоном pattern

В случае, если дополнительный параметр matches указан, он будет заполнен результатами поиска. Элемент $matches[0] будет содержать часть строки, соответствующую вхождению всего шаблона, $matches[1] - часть строки, соответствующую первой подмаске, и так далее.

flags может принимать следующие значения:

PREG_OFFSET_CAPTURE

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

Дополнительный параметр flags доступен начиная с PHP 4.3.0.

Поиск осуществляется слева направо, с начала строки. Дополнительный параметр offset может быть использован для указания альтернативной начальной позиции для поиска. Дополнительный параметр offset доступен начиная с PHP 4.3.3.

Замечание: Использование параметра offset не эквивалентно замене сопоставляемой строки выражением substr($subject, $offset) при вызове функции preg_match_all(), поскольку шаблон pattern может содержать такие условия как ^, $ или (?<=x). Сравните:

<?php
$subject = "abcdef";
$pattern = '/^def/';
preg_match($pattern, $subject, $matches, PREG_OFFSET_CAPTURE, 3);
print_r($matches);
?>

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

 Array 
(
)

В то время как этот пример

<?php
$subject = "abcdef";
$pattern = '/^def/';
preg_match($pattern, substr($subject,3), $matches, PREG_OFFSET_CAPTURE);
print_r($matches);
?>

выведет следующее:

  Array 
(
[0] => Array
(
[0] => def
[1] => 0
)

)

Функция preg_match() возвращает количество найденных соответствий. Это может быть 0 (совпадения не найдены) и 1, поскольку preg_match() прекращает свою работу после первого найденного совпадения. Если необходимо найти либо сосчитать все совпадения, следует воспользоваться функцией preg_match_all(). Функция preg_match() возвращает FALSE в случае, если во время выполнения возникли какие-либо ошибки.

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

Пример. Поиск подстроки "php" в тексте

<?php
// Символ "i" после закрывающего ограничителя шаблона означает
// регистронезависимый поиск.if (preg_match("/php/i", "PHP is the web scripting language of choice.")) {
echo "Вхождение найдено.";
} else {
echo "Вхождение не найдено.";
}
?>

Пример 2. Поиск слова "web" в тексте

<?php
/*
Специальная последовательность \b в шаблоне означает границу слова,
следовательно, только изолированное вхождение слова 'web' будет соответствовать
маске, в отличие от "webbing" или "cobweb".
*/
if (preg_match("/\bweb\b/i", "PHP is the web scripting language of choice.")) {
echo "Вхождение найдено.";
} else {
echo "Вхождение не найдено.";
}

if (preg_match("/\bweb\b/i", "PHP is the website scripting language of choice.")) {
echo "Вхождение найдено.";
} else {
echo "Вхождение не найдено.";
}
?>

Пример. Извлечение доменного имени из URL

<?php
// Извлекаем имя хоста из URL
preg_match("/^(http:\/\/)?([^\/]+)/i",
"http://www.php.net/index.html", $matches);
$host = $matches[2];

// извлекаем две последние части имени хостаpreg_match("/[^\.\/]+\.[^\.\/]+$/", $host, $matches);
echo "domain name is: {$matches[0]}\n";
?>

Результат работы примера:

domain name is: php.net

preg_quote()

Экранирует символы в регулярных выражениях
(PHP 3 >= 3.0.9, PHP 4, PHP 5)

Описание

string preg_quote ( string str [, string delimiter] )

Функция preg_quote() принимает строку str и добавляет обратный слеш перед каждым служебным символом. Это бывает полезно, если в составлении шаблона участвуют строковые переменные, значение которых в процессе работы скрипта может меняться.

В случае, если дополнительный параметр delimiter указан, он будет также экранироваться. Это удобно для экранирования ограничителя, который используется в PCRE функциях. Наиболее распространенным ограничителем является символ '/'.

В регулярных выражениях служебными считаются следующие символы: . \\ + * ? [ ^ ] $ ( ) { } = ! < > | :

preg_quote() пример

<?php$keywords = "$40 for a g3/400";
$keywords = preg_quote($keywords, "/");
echo $keywords; // возвращает \$40 for a g3\/400
?>

Пример. Выделение курсивом слова в тексте

<?php
// В данном примере preg_quote($word) используется, чтобы
// избежать трактовки символа '*' как спец. символа.
$textbody = "This book is *very* difficult to find.";
$word = "*very*";
$textbody = preg_replace ("/" . preg_quote($word) . "/",
"" . $word . "",
$textbody);
?>

preg_replace_callback()

Выполняет поиск по регулярному выражению и замену с использованием функции обратного вызова
(PHP 4 >= 4.0.5, PHP 5)

Описание

mixed preg_replace_callback ( mixed pattern, callback callback, mixed subject [, int limit] )

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

preg_replace_callback() пример

<?php
// Этот текст был использован в 2002 году
// мы хотим обновить даты к 2003 году
$text = "April fools day is 04/01/2002\n";
$text.= "Last christmas was 12/24/2001\n";

// функция обратного вызова
function next_year($matches)
{
// как обычно: $matches[0] - полное вхождение шаблона
// $matches[1] - вхождение первой подмаски,
// заключенной в круглые скобки, и так далее...
return $matches[1].($matches[2]+1);
}

echo preg_replace_callback(
"|(\d{2}/\d{2}/)(\d{4})|",
"next_year",
$text);

// результат:
// April fools day is 04/01/2003
// Last christmas was 12/24/2002
?>

Достаточно часто callback функция, кроме как в вызове preg_replace_callback(), ни в чем больше не участвует. Исходя из этих соображений, можно использовать create_function() для создания безымянной функции обратного вызова непосредственно в вызове preg_replace_callback(). Если вы используете такой подход, вся информация, связанная с заменой по регулярному выражению, будет собрана в одном месте, и пространство имен функций не будет загромождаться неиспользуемыми записями.

Пример. preg_replace_callback() и create_function()

<?php
/* фильтр, подобный тому, что используется в системах Unix
* для преобразования в заглавные начальных букв параграфа */

$fp = fopen("php://stdin", "r") or die("can't read stdin");
while (!feof($fp)) {
$line = fgets($fp);
$line = preg_replace_callback(
'|

\s*\w|',
create_function(
// Использование одиночных кавычек в данном случае принципиально,
// альтернатива - экранировать все символы '$'
'$matches',
'return strtolower($matches[0]);'
),
$line
);
echo $line;
}
fclose($fp);
?>

preg_replace()

Выполняет поиск и замену по регулярному выражению
(PHP 3 >= 3.0.9, PHP 4, PHP 5)

Описание

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.

Пример 1. Использование подмасок, за которыми следует цифра

<?php$string = "April 15, 2003";
$pattern = "/(\w+) (\d+), (\d+)/i";
$replacement = "\${1}1,\$3";
echo preg_replace($pattern, $replacement, $string);
?>

Результатом работы этого примера будет:

April1,2003

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

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

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

<?php$string = "The quick brown fox jumped over the lazy dog.";

$patterns[0] = "/quick/";
$patterns[1] = "/brown/";
$patterns[2] = "/fox/";

$replacements[2] = "bear";
$replacements[1] = "black";
$replacements[0] = "slow";

echo preg_replace($patterns, $replacements, $string);
?>

Результат:

The bear black slow jumped over the lazy dog.

Используя ksort(), получаем желаемый результат:

<?php
ksort($patterns);
ksort($replacements);

echo preg_replace($patterns, $replacements, $string);

?>

Результат:

The slow black bear jumped over the lazy dog.

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

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

Модификатор /e меняет поведение функции preg_replace() таким образом, что параметр replacement после выполнения необходимых подстановок интерпретируется как PHP-код и только после этого используется для замены. Используя данный модификатор, будьте внимательны: параметр replacement должен содержать корректный PHP-код, в противном случае в строке, содержащей вызов функции preg_replace(), возникнет ошибка синтаксиса.

Пример. Замена по нескольким шаблонам

<?php$patterns = array ("/(19|20)(\d{2})-(\d{1,2})-(\d{1,2})/",
"/^\s*{(\w+)}\s*=/");
$replace = array ("\\3/\\4/\\1\\2", "$\\1 =");
echo preg_replace($patterns, $replace, "{startDate} = 1999-5-27");
?>

Этот пример выведет:

$startDate = 5/27/1999

Пример. Использование модификатора /e

<?phppreg_replace("/(<\/?)(\w+)([^>]*>)/e",
"'\\1'.strtoupper('\\2').'\\3'",
$html_body);
?>

Преобразует все HTML-теги к верхнему регистру

Пример. Конвертор HTML в текст

<?php
// $document на выходе должен содержать HTML-документ.
// Необходимо удалить все HTML-теги, секции javascript,
// пробельные символы. Также необходимо заменить некоторые
// HTML-сущности на их эквивалент.
$search = array ("']*?>.*?'si", // Вырезает javaScript
"'<[\/\!]*?[^<>]*?>'si", // Вырезает HTML-теги
"'([\r\n])[\s]+'", // Вырезает пробельные символы
"'&(quot|#34);'i", // Заменяет HTML-сущности
"'&(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"); // интерпретировать как php-код
$replace = array ("",
"",
"\\1",
"\"",
"&",
"<",
">",
" ",
chr(161),
chr(162),
chr(163),
chr(169),
"chr(\\1)");

$text = preg_replace($search, $replace, $document);
?>

Замечание: Параметр limit доступен в PHP 4.0.1pl2 и выше.

preg_split()

Разбивает строку по регулярному выражению (PHP 3 >= 3.0.9, PHP 4, PHP 5)

Описание

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

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

Пример 1. preg_split() пример: Получение подстрок из заданного текста

<?php
// разбиваем строку по произвольному числу запятых и пробельных символов,
// которые включают в себя " ", \r, \t, \n и \f$keywords = preg_split("/[\s,]+/", "hypertext language, programming");
?>

Пример 2. Разбиваем строку на составляющие символы

<?php$str = 'string';
$chars = preg_split('//', $str, -1, PREG_SPLIT_NO_EMPTY);
print_r($chars);
?>

Пример 3. Разбиваем строку с указанием смещения для каждой из найденных подстрок

<?php$str = 'hypertext language programming';
$chars = preg_split('/ /', $str, -1, PREG_SPLIT_OFFSET_CAPTURE);
print_r($chars);
?>

На выходе получаем:

Array(
[0] => Array
(
[0] => hypertext
[1] => 0
)

[1] => Array
(
[0] => language
[1] => 10
)

[2] => Array
(
[0] => programming
[1] => 19
)

)

Замечание: Параметр flags был добавлен в PHP 4 Beta 3.

Примеры использования preg_grep()

Пример 1. Возвращает все элементы массива, содержащие числа с плавающей точкой

<?php$fl_array = preg_grep("/^(\d+)?\.\d+$/", $array);
?>

Пример 2. Возвращает ключи элементов массива, содержащих искомый паттерн (строку поиска)

<?phpfunction preg_array_key( $PatternString, $InputArray ){
return key( preg_grep( $PatternString, $InputArray ) );
}
?>

Пример 3. Возвращает массив элементов, не содержащих строку поиска

<?php$nomatch = preg_grep("/{$keyword}/i",$array,PREG_GREP_INVERT);
?>

Пример 4. Cпособ защиты от попыток SQL-инъекций.

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

'/[\'")]* *[oO][rR] *.*(.)(.) *= *\\2(?:--)?\\1?/'

Использование:

<?php$SQLInjectionRegex = '/[\'")]* *[oO][rR] *.*(.)(.) *= *\\2(?:--)?\\1?/';
$suspiciousQueryItems = preg_grep($SQLInjectionRegex, $_REQUEST);
?>

Код обнаруживает следующие строки (полностью, регистронезависимо, a=любой символ):

' or 1=1--
" or 1=1--
or 1=1--
' or 'a'='a
" or "a"="a
') or ('a'='a