Подшаблоны однократного действия

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

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

 

Представьте, к примеру, что шаблон \d+foo будет применен к исходной строке

123456bar

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

(?>\d+)bar

Такой тип записи "блокирует" часть шаблона, которую он содержит, таким образом, что как только совпадение будет найдено, нет необходимости в повторном сравнении этой части шаблона.

 

Другими словами, такой тип подшаблона совпадает со строкой символов, с которой бы он совпал в обычном виде, если бы был "привязан" (anchored) к текущей позиции исходной строки.

 

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

 

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

 

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

abcd$

в применении к длинной строке, с которой он не совпадает. Так как процесс сравнения происходит слева направо, PCRE будет искать каждое вхождение буквы "a" в исходную строку, а затем проверять на совпадение остаток шаблона. Если указан шаблон

^.*abcd$

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

^(?>.*)(?<=abcd)

то начальный ".*" совпадет сразу со всей строкой и никаких откатов назад не будет. Последующее назадсмотрящее утверждение делает единственную проверку последних четырех символов. Если эта проверка окажется неудачной, то все сравнение тут же завершится с неудачей. Для длинных строк такой подход позволяет существенно снизить время проверки шаблона.