Решить Катастрофический Обратный путь в моих ссылках для обнаружения регулярных выражений? - PullRequest
0 голосов
/ 17 января 2019

У меня есть выражение для поиска ссылок в текстах:

(?i)\\b((?:https?://|www\\d{0,3}[.]|[a-z0-9.\\-]+[.][a-z]{2,4}/)(?:[^'\"\\n\\r()<>]+|\\(([^'\"\\n\\r()<>]+|(\\([^'\"\\n\\r()<>]+\\)))*\\))+(?:\\(([^'\"\\n\\r()<>]+|(\\([^'\"\\n\\r()<>]+\\)))*\\)|[^'\"\\n\\r`!()\\[\\]{};:'.,<>?\u00AB\u00BB\u201C\u201D\u2018\u2019]))

Но некоторые ( в ссылке вызывают блокировку потока. Ища в Интернете, я нашел какой-то веб-сайт, предполагающий, что это проблема катастрофического возврата. Я потратил некоторое время, чтобы оптимизировать шаблон, но он не работает. Есть идеи?

Пример входной ссылки, которая вызывает проблему:

https://subdomain.domain.com/web/?id=-%c3%a1(%c2%81y%e2%80%9a%c3%a5d%e2%80%ba%c3%a8%c2%a7%c2%be.%c3%a9+%c2%a8

1 Ответ

0 голосов
/ 17 апреля 2019

Вы должны придерживаться принципа: все последующие смежные подшаблоны не могут совпадать в одном и том же месте строки.Если вы определяете их с помощью * или ?, убедитесь, что эти обязательные шаблоны перед ними не соответствуют одному и тому же тексту.Иначе, обновите образец.Или используйте атомные группировки .

Часть (?:https?://|www\d{0,3}[.]|[a-z0-9.-]+[.][a-z]{2,4}/) является чередованием, где оба могут совпадать в одном и том же месте строки.Этого нельзя избежать, поэтому используйте атомарную группу, чтобы предотвратить возврат в шаблон.

Посмотрите на [a-z0-9.-]+[.], . присутствует в классе + количественных символов.Сделайте его более линейным, замените его на [a-z0-9-]*(?:\.[a-z0-9-]*)*\..

. (?:[^'"\n\r()<>]+|\(([^'"\n\r()<>]+|(\([^'"\n\r()<>]+\)))*\))+ часть является ошибочным шаблоном: [^'"\n\r()<>]+ равен + количественно, и снова, и это приводит к ситуациям, когда механизм регулярных выражений уменьшает егодо (?:a+)+, классический сценарий CA.Используйте атомарные группировки, если вы не хотите повторно выбирать, хотя это, кажется, является частью шаблона, соответствующего сбалансированным скобкам, и может быть переписано как [^'"\n\r()<>]*(?:\((?>[^()]+|(?<o>\()|(?<-o>\)))*(?(o)(?!))\)[^'"\n\r()<>]*)*.

Часть ([^'"\n\r()<>]+|(\([^'"\n\r()<>]+\)))* похожав приведенной выше части измените ( на (?>, где вы определите количество группы и единый обязательный шаблон внутри нее.

Фиксированный шаблон -

var pattern = @"(?i)\b((?>https?://|www\d{0,3}\.|[a-z0-9-]*(?:\.[a-z0-9-]*)*\.[a-z]{2,4}/)(?>[^'""\n\r()<>]+|\((?>[^'""\n\r()<>]+|\([^'""\n\r()<>]+\))*\))+(?:\((?>[^'""\n\r()<>]+|(\([^'""\n\r()<>]+\)))*\)|[^]['""\n\r`!(){};:.,<>?\u00AB\u00BB\u201C\u201D\u2018\u2019]))";

См. какэто изящно терпит неудачу здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...