Это катастрофически возвращает назад к длинным последовательностям пробелов, которые появляются после последнего закрывающего тега </tag:main>
.Рассмотрим случай, когда строка темы заканчивается 100 пробелами.Сначала он сопоставляет их со знаком .
слева от чередования.Это терпит неудачу, потому что нет закрывающего тега, поэтому он пытается сопоставить последний символ с \s
.Это тоже не удается, поэтому он пытается сопоставить второй с последним пробел как \s
и последний пробел как .
.Это терпит неудачу (все еще без закрывающего тега), поэтому он пробует последний пробел как \s
.Если это не удается, он соответствует пробелу от третьего до последнего как \s
и пробует все 4 способа сопоставить последние два пробела.Когда это не удается, он пробует четвертый-последний пробел как \s
и все 8 путей в последних 3 пробелах.Затем 16, 32 и т. Д. Вселенная заканчивается до того, как достигает 100-го-последнего пространства.
Разные виртуальные машины по-разному реагируют на совпадения регулярных выражений, которые происходят вечно из-за катастрофического возврата.Некоторые просто сообщат «нет совпадения».В V8 это похоже на написание любого другого бесконечного или почти бесконечного цикла.
Использование не жадного *
будет делать то, что вы хотите (вы хотите остановиться на первом </tag:main>
, а не на последнем), нобудет по-прежнему выполнять катастрофическое обратное отслеживание для длинных строк пробелов, в которых отсутствует закрывающая последовательность.
Убедившись, что одинаковые символы во внутренней скобке не могут совпадать с обеими сторонами чередования, уменьшит проблему с экспоненциальной дотот, который является линейным по длине строки.Используйте класс символов вместо чередования или поместите \n
справа от чередования.\n
не пересекается с .
, поэтому, если вы нажмете длинную последовательность пробелов, механизм регулярных выражений не пробует все комбинации слева-справа-слева и т. Д. До завершения.