У меня есть это регулярное выражение:

^((?:(?:\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);

Мой вопрос довольно прост: почему вторая строка не совпадает?

3
dader 11 Май 2011 в 20:41
Просто любопытно; что вы пытаетесь сделать (например, какова ваша общая цель)? Может быть более простое решение вашей проблемы, кроме регулярных выражений.
 – 
Vivin Paliath
11 Май 2011 в 20:43
Попробуйте получить все имена методов класса в файле, не используя Reflection, ни токенизатор php.
 – 
dader
11 Май 2011 в 20:48
Я знаю, что это грязно, но мне нужно, чтобы это было!
 – 
dader
11 Май 2011 в 20:57

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. Количество перестановок растет экспоненциально с каждым символом. Вы еще больше усложняете ситуацию, делая всю группу необязательной (?, окружающий все это).

3
Tim Pietzcker 11 Май 2011 в 21:02
Я воспроизвел проблему в PHP 5.3 и включил отчет об ошибках - никаких сообщений об ошибках или предупреждений не было. Мне было бы интересно узнать, почему это не удается в PHP
 – 
Erik
11 Май 2011 в 20:54
Я не знал о притяжательном квантификаторе! Но это так мило!
 – 
dader
11 Май 2011 в 20:55
Есть preg_last_error(), который должен возвращать код ошибки, если он действительно достиг предела "слишком длинного" имени функции.
 – 
Marc B
11 Май 2011 в 20:55
Я думаю, может быть в случае memory_limit до low? - нет, это не так
 – 
dader
11 Май 2011 в 20:56

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

gskinner

0
Khurram Ijaz 11 Май 2011 в 20:48
Почему многострочный вообще на это влияет? Его одна строка ... даже если она работает, это бессмысленное решение и, вероятно, все равно будет ломаться в других крайних случаях по какой-либо причине, вызывающей проблему, с которой начинается
 – 
Erik
11 Май 2011 в 20:52