Почему это регулярное выражение «замораживает» программу в VC ++? - PullRequest
0 голосов
/ 08 мая 2018

У меня есть следующий код, изначально запрограммированный с использованием библиотеки регулярных выражений C ++ 11 (#include <regex>), но теперь использующий Boost для устранения неполадок:

boost::regex reg(R"(.*?((?:[a-z][a-z]+)).*?((?:[a-z][a-z]+)).*?((?:[a-z][a-z]*[0-9]+[a-z0-9]*)).*?((?:[a-z][a-z]+)).*?((?:[a-z][a-z0-9_]*)).*?((?:[a-z][a-z0-9_]*)).*?(\d+).*?((?:[a-z][a-z0-9_]*)).*?((?:[a-z][a-z0-9_]*)).*?((?:[a-z][a-z0-9_]*)).*?(\d+).*?((?:[a-z][a-z0-9_]*)).*?(\d+).*?((?:[a-z][a-z0-9_]*)).*?((?:[a-z][a-z0-9_]*)).*?((?:[a-z][a-z0-9_]*)).*?(\d+).*?((?:[a-z][a-z0-9_]*)).*?(\d+).*?((?:[a-z][a-z]+)).*?(\d+).*?((?:[a-z][a-z]+)))", boost::regex::icase);
boost::cmatch matches;

if (boost::regex_match(request, reg) && matches.size() > 1)
{
    printf("Match found");
}
else
{
    printf("No match.");
}

При выполнении этот код кажется "зависшим" на boost::regex_match(request, reg), как будто он занимает много времени для обработки. Я подождал пять минут для его обработки (в случае, если это проблема обработки), но состояние программы было таким же.

Я проверил версию вышеуказанного кода библиотеки STL regex онлайн на cpp.sh и onlinegdb , и там он работает без нареканий. Затем я скопировал этот код в проект VC ++, и код снова зависает:

#include <iostream>
#include <string>
#include <regex>

int main()
{
    std::string request = "\\login\\\\challenge\\jRJkdflp3gvTzrwiQ3tyKSqnyppmaZog\\uniquenick\\Lament\\partnerid\\0\\response\\4767846ef255a88da9b10f7c923a1e6e\\port\\-14798\\productid\\11489\\gamename\\crysiswars\\namespaceid\\56\\sdkrevision\\3\\id\\1\\final\\";
    std::regex reg(R"(.*?((?:[a-z][a-z]+)).*?((?:[a-z][a-z]+)).*?((?:[a-z][a-z]*[0-9]+[a-z0-9]*)).*?((?:[a-z][a-z]+)).*?((?:[a-z][a-z0-9_]*)).*?((?:[a-z][a-z0-9_]*)).*?(\d+).*?((?:[a-z][a-z0-9_]*)).*?((?:[a-z][a-z0-9_]*)).*?((?:[a-z][a-z0-9_]*)).*?(\d+).*?((?:[a-z][a-z0-9_]*)).*?(\d+).*?((?:[a-z][a-z0-9_]*)).*?((?:[a-z][a-z0-9_]*)).*?((?:[a-z][a-z0-9_]*)).*?(\d+).*?((?:[a-z][a-z0-9_]*)).*?(\d+).*?((?:[a-z][a-z]+)).*?(\d+).*?((?:[a-z][a-z]+)))", std::regex::icase);
    std::smatch matches;

    if (std::regex_search(request, matches, reg) && matches.size() > 1)
    {
        printf("Match found");
    }
    else
    {
        printf("No match.");
    }
}

Соответствующая строка:

\ Логин \ вызов \ jRJwdflp3gvTrrwiQ3tyKSqnyppmaZog \ uniquenick \ User \ Partnerid \ 0 \ ответ \ 4767846ef255a83da9b10f7f923a1e6e \ порт-14798 \ ProductID \ 11489 \ GameName \ crysiswars \ namespaceid \ 56 \ sdkrevision \ 3 \ идентификатор \ 1 \ окончательный \

Я протестировал тот же код на установке Visual Studio 2017 на другом компьютере (новый проект) и получил точно такой же результат ... который, кажется, указывает на то, что что-то, что делает компилятор, заставляет код зависать / принимать долгое время обработки. Я не могу проверить другой компилятор локально.

Строка регулярного выражения проверяет regex101 , поэтому функционально выражение в порядке.

Это для Visual Studio 2017 Professional с таргетингом v141.

Почему это происходит и как я могу это исправить?

1 Ответ

0 голосов
/ 08 мая 2018

Ваша проблема связана с возвратом.
В семпле boost вы используете regex_match, что приводит к совпадению всей строки
.
Вы получите тот же результатпри использовании regex_search и добавлении ^..$.

Однако ваша строка никогда не может совпадать, потому что вы заставили ее заканчивать
на букве, но строка действительно заканчивается обратной косой чертой.
Это заставляет двигатель повторить все эти .*?позиции.

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

Могут помочь и другие вещи, вы можете немного очистить свое регулярное выражение и / или добавить несколько
атомных групп и / или добавить некоторые косые черты вместо этих .*?

В любом случае,используйте это:

^.*?((?:[a-z][a-z]+)).*?((?:[a-z][a-z]+)).*?((?:[a-z][a-z]*[0-9]+[a-z0-9]*)).*?((?:[a-z][a-z]+)).*?((?:[a-z][a-z0-9_]*)).*?((?:[a-z][a-z0-9_]*)).*?(\d+).*?((?:[a-z][a-z0-9_]*)).*?((?:[a-z][a-z0-9_]*)).*?((?:[a-z][a-z0-9_]*)).*?(\d+).*?((?:[a-z][a-z0-9_]*)).*?(\d+).*?((?:[a-z][a-z0-9_]*)).*?((?:[a-z][a-z0-9_]*)).*?((?:[a-z][a-z0-9_]*)).*?(\d+).*?((?:[a-z][a-z0-9_]*)).*?(\d+).*?((?:[a-z][a-z]+)).*?(\d+).*?((?:[a-z][a-z]+)).*?$

Вывод

 **  Grp 0 -  ( pos 0 : len 207 ) 
\login\challenge\jRJwdflp3gvTrrwiQ3tyKSqnyppmaZog\uniquenick\User\partnerid\0\response\4767846ef255a83da9b10f7f923a1e6e\port-14798\productid\11489\gamename\crysiswars\namespaceid\56\sdkrevision\3\id\1\final\  
 **  Grp 1 -  ( pos 1 : len 5 ) 
login  
 **  Grp 2 -  ( pos 7 : len 9 ) 
challenge  
 **  Grp 3 -  ( pos 17 : len 32 ) 
jRJwdflp3gvTrrwiQ3tyKSqnyppmaZog  
 **  Grp 4 -  ( pos 50 : len 10 ) 
uniquenick  
 **  Grp 5 -  ( pos 61 : len 4 ) 
User  
 **  Grp 6 -  ( pos 66 : len 9 ) 
partnerid  
 **  Grp 7 -  ( pos 76 : len 1 ) 
0  
 **  Grp 8 -  ( pos 78 : len 8 ) 
response  
 **  Grp 9 -  ( pos 94 : len 25 ) 
ef255a83da9b10f7f923a1e6e  
 **  Grp 10 -  ( pos 120 : len 4 ) 
port  
 **  Grp 11 -  ( pos 125 : len 5 ) 
14798  
 **  Grp 12 -  ( pos 131 : len 9 ) 
productid  
 **  Grp 13 -  ( pos 141 : len 5 ) 
11489  
 **  Grp 14 -  ( pos 147 : len 8 ) 
gamename  
 **  Grp 15 -  ( pos 156 : len 10 ) 
crysiswars  
 **  Grp 16 -  ( pos 167 : len 11 ) 
namespaceid  
 **  Grp 17 -  ( pos 179 : len 2 ) 
56  
 **  Grp 18 -  ( pos 182 : len 11 ) 
sdkrevision  
 **  Grp 19 -  ( pos 194 : len 1 ) 
3  
 **  Grp 20 -  ( pos 196 : len 2 ) 
id  
 **  Grp 21 -  ( pos 199 : len 1 ) 
1  
 **  Grp 22 -  ( pos 201 : len 5 ) 
final  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...