具有奇怪行为的std :: regex_match和懒惰量词

时间:2017-02-23 17:47:19

标签: c++ regex c++11 non-greedy

我知道:
懒惰量词匹配:尽可能少(最短匹配)

也知道构造函数:

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

和:
ECMAScript支持非贪婪匹配,
ECMAScript正则表达式"<tag[^>]*>.*?</tag>"
仅匹配第一个结束标记... en.cppreference

和:
最多只能从ECMAScript中选择一个语法选项, basicextendedawkgrepegrep。如果没有选择语法, 假设选择ECMAScript ... en.cppreference

和:
请注意,regex_match只会将正则表达式与整个字符序列成功匹配,而std::regex_search会成功匹配子序列... std::regex_match

这是我的代码:+ Live

#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

返回.+?

事实上,在这里,非贪婪 .+?量词的含义与贪婪一,/.+?/和{{ 1}}匹配相同的字符串。它们是不同的模式。 问题是为什么忽略问号?

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_searchs?无关紧要,g?仍然匹配整个字符串!

更多详情

/.*?/

1 个答案:

答案 0 :(得分:1)

我没有看到任何不一致。 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$ )