Я должен признать, что это тоже меня удивило, но я получаю тот же результат в RegexBuddy: он прекращает попытки после миллиона шагов. Я знаю, что предупреждения о катастрофическом обратном трафике, как правило, сосредоточены на вложенных квантификаторах, но, по моему опыту, чередование, по крайней мере, опасно. На самом деле, если я изменю последнюю часть вашего регулярного выражения на это:
'(?:[^']+|'')+'
... к этому:
'(?:[^']*(?:''[^']*)*)'
... он терпит неудачу только одиннадцать шагов , Это пример метода Friedl «развернутого цикла», который он разбивает следующим образом:
opening normal * ( special normal * ) * closing
' [^'] '' [^'] '
Вложенные звезды безопасны, если:
special
и normal
никогда не могут совпадать с одним и тем же, special
всегда совпадает хотя бы с одним символом, а special
атомный (для него должен быть только один способ). Регулярное выражение будет сбой в соответствии с минимальным обратным отсчетом, а - без возврата. С другой стороны, альтернативная версия почти гарантированно отступает, и там, где совпадение невозможно, она быстро выходит из-под контроля по мере увеличения длины целевой строки. Если он не слишком сильно отступает в некоторых вариантах, то это связано с тем, что у них есть оптимизация, встроенная специально для противодействия этой проблеме - до сих пор есть что-то очень малое.
Может кто-нибудь объяснить, почему механизм regex java переходит в катастрофический режим этого регулярного выражения?
blockquote>Для строки:
'pão de açúcar itaucard mastercard platinum SUSTENTABILIDADE])
Кажется, что это часть регулярного выражения была бы проблемой:
'(?:[^']+|'')+'
Соответствие первой
'
, а затем неспособность совместить закрытие'
и, таким образом, отмена всех комбинаций вложенных кванторов.Если вы разрешаете регулярному выражению возвращаться, он будет отступать (при сбое). Используйте атомарные группы и / или притяжательные квантификаторы, чтобы предотвратить это.
Btw, вам не нужна большая часть экранов в этом регулярном выражении. Единственное, что вам (возможно) нужно избегать в классах символов (
[]
) - это символы^-]
. Но обычно вы можете позиционировать их так, чтобы им тоже не нужно было бежать. Конечно,\
и все, что вы хотите, quoation, строка должна быть (двойной) экранирована."^(?:[^]['\"\\s~:/@#|^&(){}\\\\][^][\"\s~:/@#|^&(){}\\\\]*|\"(?:[^\"]++|\"\")++\"|'(?:[^']++|'')++')"
^
нужно только экранировать, если это первый символ, а -
требуется только экранирование, если оно не является терминалом (первым или последним). Но это не имеет значения: я до сих пор считаю эту картину совершенно нечитаемой и недостижимой. Это действительно попадает под мою кожу, когда люди пишут такие вещи. Я знаю, что вы просто подражаете оригиналу, но оригинал заслуживает упрека, а не подражания.
– tchrist
11 September 2011 в 17:48
[^']+
, так и(?:[^']+|'')+
зачисляются отдельно для того, чтобы сжигать все после начального'
, а затем есть три так называемого «обратного пути». перед тем, как он сделает что-нибудь, I i> будет вызывать обратное отслеживание. – Alan Moore 11 September 2011 в 18:10