Подмаски

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

  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 соответственно. Максимальное количество захватывающих подмасок - 65535. Такие большие шаблоны могут не скомпилироваться, в зависимости от настроек libpcre.

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

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

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

Также можно использовать именованные подмаски с помощью синтаксиса (?P<name>pattern). Эта подмаска будет индексирована в массиве совпадений кроме обычного числового индекса, еще и по имени name. В PHP 5.2.2 было добавлено два альтернативных синтаксиса: (?<name>pattern) и (?'name'pattern).

Иногда бывает необходимо иметь несколько совпадений, исключающих друг друга. Обычно, каждое такое совпадение получает свой собственный номер, даже если шаблон позволяет совпасть только одному из них. Синтаксис (?| позволяет обойти это поведение и убрать дублирующиеся номера. Рассмотрим следующее регулярное выражение, сопоставленное со строкой Sunday:

(?:(Sat)ur|(Sun))day

Здесь Sun сохраняется в ссылке 2, тогда как ссылка 1 пуста. Если же совпадет Sat, то она будет помещена в ссылку 1, а ссылка 2 вообще не будет существовать. Использование (?| в шаблоне решает эту проблему:

(?|(Sat)ur|(Sun))day

В этом шаблоне обе подмаски Sun и Sat будут сохранены под номером 1.