Почему проверка этой строки с помощью Regex.IsMatch приводит к тому, что процессор достигает 100%?

При использовании Regex.IsMatch (С#,.Net 4.5) на определенной строке ЦП достигает 100%.

Строка:

https://www.facebook.com/CashKingPirates/photos/a.197028616990372.62904.196982426994991/1186500984709792/?type=1&permPage=1

шаблон:

^http(s)?://([\w-]+.)+[\w-]+(/[\w- ./?%&=])?$

Полный код:

Regex.IsMatch("https://www.facebook.com/CashKingPirates/photos/a.197028616990372.62904.196982426994991/1186500984709792/?type=1&permPage=1",
                @"^http(s)?://([\w-]+.)+[\w-]+(/[\w- ./?%&=])?$");

Я обнаружил, что изменение URL-адреса предотвращает эту проблему. Измененный URL:

https://www.facebook.com/CashKingPirates/photos/a.197028616990372.62904.196982426994991/1186500984709792

Но все еще очень заинтересовано в понимании того, что вызывает это.

Ответы

Ответ 1

Как указывал nu11p01n73R, у вас есть много обратного отслеживания с вашим регулярным выражением. Это потому, что части вашего выражения могут соответствовать одному и тому же, что дает двигателю множество вариантов, которые он должен попробовать, прежде чем найти результат.

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

Это уже должно значительно сократить обратный трафик и сделать его быстрым:

^http(s)?://([\w-]+\.)+[\w-]+(/[\w- ./?%&=])?$

И если вы хотите на самом деле сопоставить исходную строку, вам нужно добавить квантификатор в класс символов в конце:

^http(s)?://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]+)?$
                                           ↑

Ответ 2

Я предлагаю вам проверить http://regexr.com/ веб-сайт, чтобы проверить ваше регулярное выражение.

Исправленная версия вашего регулярного выражения такова:

^(https?://(?:[\w]+\.?[\w]+)+[\w]/?)([\w\./]+)(\?[\w-=&%]+)?$

Он также имеет 3 группы:

  • group1 = Основной URL (например: facebook.com)
  • group2 = Sub urls (например:/CashKingPirates/photos/a.197028616990372.62904.196982426994991/1186500984709792/
  • group3 = Переменные (например:? type = 1 & permPage = 1)

Также помните, что для проверки фактического характера точки (.) в вашем регулярном выражении вы должны использовать \. не.

Ответ 3

Ваше регулярное выражение страдает от catastrophic backtracking. Вы можете просто использовать

^http(s)?://([\w.-])+(/[\w ./?%&=-]+)*$

См. демонстрацию.

https://regex101.com/r/cK4iV0/15