У меня есть это регулярное выражение:
^((?:(?:\s*[a-zA-Z0-9]+)*)?)\s*function\s+([_a-zA-Z0-9]+)\s+\(\s*(.*)\s*\)\s*
Чтобы соответствовать этой строке:
public function private ($var,Type $typed, $optional = 'option');
Это работает, но когда дело доходит до этого:
public function privateX ($var,Type $typed, $optional = 'option');
Это не удается.
Я заметил, что когда длина имени функции превышает 6 символов, оно больше не совпадает.
Вот полный код:
$strA = 'public function 6Chars ($var,Type $typed, $optional = "option");';
$strB = 'public function MoreThan7 ($var,Type $typed, $optional = "option");';
preg_match('!^((?:(?:\s*[a-zA-Z0-9]+)*)?)\s*function\s+([_a-zA-Z0-9]+)\s+\(\s*(.*)\s*\)\s*!',$strA,$mA);
preg_match('!^((?:(?:\s*[a-zA-Z0-9]+)*)?)\s*function\s+([_a-zA-Z0-9]+)\s+\(\s*(.*)\s*\)\s*!',$strB,$mB);
print_r($mA);
print_r($mB);
Мой вопрос довольно прост: почему вторая строка не совпадает?
2 ответа
Я не могу воспроизвести это в RegexBuddy; оба объявления совпадают. Однако шаги, необходимые механизму регулярных выражений для достижения совпадения, удваиваются с каждым символом. Имя функции из 6 символов занимает около 100 000 шагов механизма регулярных выражений, 7 символов - 200 000 шагов, 8 символов - 400 000 шагов и т. Д.
Возможно, механизм регулярных выражений отказывает после определенного количества шагов?
Притяжательный квантификатор (++
) резко сокращает количество необходимых шагов за счет уменьшения возможных перестановок, которые должен пройти механизм регулярных выражений - 50 шагов независимо от длины имени функции.
!^((?:(?:\s*[a-zA-Z0-9]++)*)?)\s*function\s+([_a-zA-Z0-9]+)\s+\(\s*(.*)\s*\)\s*!
Причина катастрофического отката, который вы видите в своем регулярном выражении, заключается в следующем:
(?:(?:\s*[a-zA-Z0-9]+)*)
Вы вкладываете квантификаторы и сделали пробелы необязательными. Поэтому ABC
можно сопоставить как ABC
, A
/ BC
, AB
/ C
или A
/ B
/ C
. Количество перестановок растет экспоненциально с каждым символом. Вы еще больше усложняете ситуацию, делая всю группу необязательной (?
, окружающий все это).
preg_last_error()
, который должен возвращать код ошибки, если он действительно достиг предела "слишком длинного" имени функции.
Вам просто нужно включить флаг /multiline /m
, и тогда он будет соответствовать обеим строкам, которые я тестировал, это подтверждается ниже. ваше здоровье
Похожие вопросы
Новые вопросы
php
PHP — это открытый, мультипарадигмальный, динамически типизированный и интерпретируемый язык сценариев, изначально разработанный для веб-разработки на стороне сервера. Используйте этот тег для вопросов о программировании на языке PHP.