Повторения

Наверх  Предыдущий  Следующий

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

· единственный символ, возможно предваренный символом обратной косой черты "\"
· метасимвол точка "."
· класс символов
· обратная ссылка (смотри следующий раздел)
· подшаблон в скобках, если он не является утверждением (смотри ниже)

 

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

z{2,4}

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

[aeiou]{3,}

требует как минимум три, последовательно идущие гласные, в то время как шаблон

\d{8}

требует ровно восемь цифр. Если отрывающаяся фигурная скобка находится в месте, где квантификатор недопустим, или если подобный синтаксис квантификатора недопустим, она рассматривается как обычный символ без специального значения. К примеру, {,6} не является квантификатором, а рассматривается как четыре отдельных символа.

 

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

 

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

 

*

Эквивалентно {0,}

+

Эквивалентно {1,}

?

Эквивалентно {0,1}

 

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

(a?)*

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

 

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

/\*.*\*/

провалится для строки

/* first command */  not comment  /* second comment */

так как, из-за "жадности" конструкции ".*", совпадение произойдет для всей строки.

 

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

/\*.*?\*/

будет правильно совпадать с комментариями C. Значение квантификаторов при этом не меняется, меняется только предпочтительное число совпадений. Так как знак вопроса "?" сам по себе является квантификатором, в шаблоне возможно появление удвоенного знака вопроса:

\d??\d

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

 

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

 

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

 

Если шаблон начинается с ".*" или ".{0,}" и установлена опция PCRE_DOTALL (эквивалентна опции Perl - /s) разрешая таким образом совпадение с символами перевода строки, то шаблон становится неявно "привязанным" (anchored). Это происходит из-за того, что остаток шаблона будет применяться к любому символу в исходной строке, начиная с первого, и не существует никаких промежуточных позиций. PCRE рассматривает такой шаблон так, как если бы перед ним стояла последовательность "\A". В случае, когда известно, что исходная строка не содержит символов перевода строки, и когда шаблон начинается с ".*", имеет смысл установить опцию PCRE_DOTALL, для того чтобы достигнуть этой оптимизации. Можно также использовать символ "^" для явного указания "привязки".

 

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

(tweedle[dume]{3}\s*)+

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

(a|(b))+

совпал со строкой "aba", значением второй захваченной подстроки будет "b".