Я должен признать, что это тоже меня удивило, но я получаю тот же результат в RegexBuddy: он прекращает попытки после миллиона шагов. Я знаю, что предупреждения о катастрофическом обратном трафике, как правило, сосредоточены на вложенных квантификаторах, но, по моему опыту, чередование, по крайней мере, опасно. На самом деле, если я изменю последнюю часть вашего регулярного выражения на это:
'(?:[^']+|'')+'
... к этому:
'(?:[^']*(?:''[^']*)*)'
... он терпит неудачу только одиннадцать шагов , Это пример метода Friedl «развернутого цикла», который он разбивает следующим образом:
opening normal * ( special normal * ) * closing
' [^'] '' [^'] '
Вложенные звезды безопасны, если:
special
и normal
никогда не могут совпадать с одним и тем же, special
всегда совпадает хотя бы с одним символом, а special
атомный (для него должен быть только один способ). Регулярное выражение будет сбой в соответствии с минимальным обратным отсчетом, а - без возврата. С другой стороны, альтернативная версия почти гарантированно отступает, и там, где совпадение невозможно, она быстро выходит из-под контроля по мере увеличения длины целевой строки. Если он не слишком сильно отступает в некоторых вариантах, то это связано с тем, что у них есть оптимизация, встроенная специально для противодействия этой проблеме - до сих пор есть что-то очень малое.
Да, вы можете сделать это за один цикл, объявить некоторую переменную (v_coll
) и сделать что-то вроде этого: