CascadiaPHP 2024

Повторение

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

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

Общий квантификатор повторения указывает минимальное и максимальное допустимое количество совпадений, согласно двум числам в фигурных скобках, разделённым запятой. Числа должны быть меньше чем 65 536, и первое число не должно превышать второе по значению. Например: z{2,4} соответствует «zz», «zzz» или «zzzz». Закрывающая фигурная скобка сама по себе — не специальный символ. Если второе число опустили, но запятую поставили, нет верхнего предела; Если и второе число, и запятую опустили, требуется точное число повторений. Поэтому шаблон [aeiou]{3,} соответствует как минимум трём последовательным гласным, а также любому количеству гласных выше трёх, тогда как шаблон \d{8} соответствует ровно восьми цифрам. Открывающая фигурная скобка, расположенная в недопустимой для квантификатора позиции, либо не соответствующая синтаксису квантификатора, интерпретируется как обыкновенная символьная строка. Например, {,6} — не квантификатор, а интерпретируется как символьная строка из четырёх символов.

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

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

Односимвольные квантификаторы
* эквивалентен {0,}
+ эквивалентен {1,}
? эквивалентен {0,1}

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

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

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

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

Если установили опцию PCRE_UNGREEDY (которой нет в языке Perl), квантификаторы перестают быть жадными по умолчанию, но могут становиться жадными, если за ними идёт символ «?». Говоря другими словами, знак вопроса инвертирует жадность квантификаторов.

Квантификаторы, за которыми идёт символ +, — «захватывающие». Они поглощают столько символов, сколько могут, и не возвращаются обратно для совпадения остатка шаблона. Поэтому шаблон .*abc совпадёт с «aabc», а .*+abc — нет, потому что подшаблон .*+ захватит всю строку целиком. Захватывающими квантификаторами пользуются для ускорения обработки.

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

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

Если захватывающий подшаблон повторяется, результирующим значением подшаблона будет подстрока, которая совпадает с результатом последней итерации. Например, когда шаблон (tweedle[dume]{3}\s*)+ совпадёт со значением «tweedledum tweedledee», результирующим значением подшаблона будет значение «tweedledee». Однако, если присутствуют вложенные захватывающие подшаблоны, значения, которые соответствуют этим подшаблонам, допускается устанавливать в предыдущих итерациях. Например, когда шаблон /(a|(b))+/ совпадёт со значением «aba», значением второй захваченной подстроки будет значение «b».

add a note

User Contributed Notes

There are no user contributed notes for this page.
To Top