std :: regex_match и ленивый квантификатор со странным поведением

Я знаю это:
Ленивые совпадения квантификаторов: как можно меньше (самое короткое совпадение)

Также известно, что конструктор:

basic_regex( ...,
flag_type f = std::regex_constants::ECMAScript );

А также:
ECMAScript опоры нежадным Матчи,
и ECMAScript регулярное выражение "<tag[^>]*>.*?</tag>"
будет соответствовать только до первый закрывающий тег …
en.cppreference

А также:
Максимум один вариант грамматики должен быть выбран из ECMAScript,
basic, extended, awk, grep, egrep, Если грамматика не выбрана,
ECMAScript предполагается быть выбранным …
en.cppreference

А также:
Обратите внимание, что regex_match будет только успешно сопоставлять регулярное выражение для всей последовательности символов, тогда как std::regex_search будет успешно соответствовать подпоследовательности …станд :: алгоритма regex_match


Вот мой код: + Жить

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

int main(){

std::string string( "s/one/two/three/four/five/six/g" );
std::match_results< std::string::const_iterator > match;
std::basic_regex< char > regex ( "s?/.+?/g?" );  // non-greedy
bool test = false;

using namespace std::regex_constants;

// okay recognize the lazy operator .+?
test = std::regex_search( string, match, regex );
std::cout << test << '\n';
std::cout << match.str() << '\n';
// does not recognize the lazy operator .+?
test = std::regex_match( string, match, regex, match_not_bol | match_not_eol );
std::cout << test << '\n';
std::cout << match.str() << '\n';
}

и вывод:

1
s/one/
1
s/one/two/three/four/five/six/g

Process returned 0 (0x0)   execution time : 0.008 s
Press ENTER to continue.

std::regex_match ничего не должно совпадать и должно возвращаться 0 с нежадным квантор .+?

На самом деле, здесь, нежадным .+? квантификатор имеет то же значение, что и жадный один и оба /.+?/ а также /.+/ соответствовать одной и той же строке. Это разные модели.
Итак, проблема в том, почему знак вопроса игнорируется?

regex101

Быстрый тест:

$ echo 's/one/two/three/four/five/six/g' | perl -lne '/s?\/.+?\/g?/ && print $&'
$ s/one/
$
$ echo 's/one/two/three/four/five/six/g' | perl -lne '/s?\/.+\/g?/ && print $&'
$ s/one/two/three/four/five/six/g

НОТА
это регулярное выражение: std::basic_regex< char > regex ( "s?/.+?/g?" ); нежадным
и это : std::basic_regex< char > regex ( "s?/.+/g?" ); жадный
имеют одинаковый выход с std::regex_match, Тем не менее оба соответствуют всей строке!
Но с std::regex_search имеют разный выход.
Также s? или же g? не имеет значения и с /.*?/ по-прежнему соответствует всей строке!

Более детально

g++ --version
g++ (Ubuntu 6.2.0-3ubuntu11~16.04) 6.2.0 20160901

0

Решение

Я не вижу противоречий. regex_match пытается сопоставить всю строку, так s?/.+?/g? лениво расширяется, пока вся строка не будет покрыта.

Эти «диаграммы» (для regex_searchнадеюсь, поможет получить представление о жадности

Non-greedy:

a.*?a: ababa
a|.*?a: a|baba
a.*?|a: a|baba  # ok, let's try .*? == "" first
# can't go further, backtracking
a.*?|a: ab|aba  # lets try .*? == "b" now
a.*?a|: aba|ba
# If the regex were a.*?a$, there would be two extra backtracking
# steps such that .*? == "bab".

Greedy:

a.*?a: ababa
a|.*a: a|baba
a.*|a: ababa|  # try .* == "baba" first
# backtrack
a.*|a: abab|a  # try .* == "bab" now
a.*a|: ababa|

А также regex_match( abc ) как regex_search( ^abc$ ) в этом случае.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]