Квантификаторы, их "жадность" и ее ограничение
Ознакомимся с квантификаторами, также именуемыми числителями или повторителями. Если после подшаблона стоит квантификатор, то этот шаблон может повторяться столько раз, сколько указыват этот квантификатор. Например, шаблон a{0,4} соответствует нулю, одной, двум, трем и четырем буквам "a", идущим подряд.
Соответствие нулю каких-то символов означает соответствие пустой подстроке. Если максимальный параметр не ограничен, то его можно опустить: шаблон a{1,} соответствует последовательности из одной и более букв "а". Шаблон a{3} соответствует ровно трем подряд буквам a, это то же, что и шаблон aaa.
В Perl есть ограничение на максимальное значение квантификатора: 32766. Это связано с тем, что применение квантификаторов требует запоминания состояний, чтобы в последующем в случае неудачи поиска вернуться и попробовать варианты с другим числом повторений. Этот вопрос мы рассмотрим позднее.
Некоторые числители используются так часто, что для них сделали краткие формы записи:
- a* - это нуль или больше символов a: a{0,};
- a+ - это один или больше символов a: a{1,};
- a? - это нуль или один символ a: a{0,1}.
Квантификаторы имеют высокий приоритет, поэтому шаблон bil+ing соответствует символам bi, после которых идет одна или больше букв l и далее последовательность ing. Если вы хотите, чтобы квантификатор соответствовал последовательности символов или группе подшаблонов, то эту конструкцию надо взять в скобки:
(bil)+ing соответстсвует строкам biling bilbiling bilbilbiling и т.д.
По умолчанию, алгоритм работы квантификаторов таков, что они пытаются захватить как можно больше текста, который им соответствует. Например, в переменной $text имеем текст
<b>Текст выделен жирным шрифтом.</b> Простой текст <b>Это опять жирный</b>
Если применить к этому тексту регулярное выражение <b>.+</b>: $text =~ /<b>.+</b>/ то оно будет соответствовать всему этому тексту, а не фрагменту <b>Текст выделен жирным шрифтом.</b>
Аналогично, в шаблоне
\w*a
примененном к строке
abcabcaaaaa
подшаблон \w* будет соответствовать подстроке
abcabcaaaa
(без последней буквы a), а не подстроке
abca
или
abcabca
Имеется способ заставить квантификаторы захватывать как можно меньше текста, для этого после такого квантификатора надо поставить знак вопроса: "?". Например:
a+?
соответствует минимуму из одной и более букв "a". Если этот шаблон применить к строке
bbbaaaabbb
то такой минимальный квантификатор захватит первую попавшуюся букву а, после чего оператор поиска закончит работу, вернув число 1.
В шаблоне
a*?
минимальный квантификатор удовлетворится нулем символов a, а это значит, что совпадение будет найдено в любом месте, даже после истинного конца строки! Оператор
print "a" =~ /\za*/;
напечатает 1.
Вот другие примеры минимальных квантификаторов:
\w? (abc){3,5}?