std::regex_match和std::regex_search有什么区别?

42

以下程序使用C++11的 std::regex_matchstd::regex_search 来获取“Day”信息。然而,使用第一种方法返回false,而第二种方法返回true(预期结果)。我已经阅读了文档和现有的相关SO问题,但我不理解这两种方法之间的区别以及何时应使用它们?它们可以互换地用于任何常见问题吗?

regex_match和regex_search之间的区别是什么?

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

int main()
{
    std::string input{ "Mon Nov 25 20:54:36 2013" };
    //Day:: Exactly Two Number surrounded by spaces in both side
    std::regex  r{R"(\s\d{2}\s)"};
    //std::regex  r{"\\s\\d{2}\\s"};
    std::smatch match;

if (std::regex_match(input,match,r)) {
        std::cout << "Found" << "\n";
    } else {
        std::cout << "Did Not Found" << "\n";
    }

    if (std::regex_search(input, match,r)) {
        std::cout << "Found" << "\n";
        if (match.ready()){
            std::string out = match[0];
            std::cout << out << "\n";
        }
    }
    else {
        std::cout << "Did Not Found" << "\n";
    }
}

输出

Did Not Found

Found

 25 

为什么在这种情况下第一个正则表达式方法返回 falseregex 看起来是正确的,理论上应该都返回 true。我通过将 std::regex_match(input,match,r) 更改为 std::regex_match(input,r) 运行了上面的程序,并发现它仍然返回 false。

能有人解释一下上面的例子,以及这些方法的通常用途吗?

2个回答

41

regex_match仅当整个输入序列被匹配时返回true,而regex_search即使只有子序列与regex匹配也会成功。

引用自N3337:

  

§28.11.2/2 regex_match [re.alg.match]

  Effects: 确定正则表达式e字符序列[first,last)是否完全匹配。... 如果存在这样的匹配,则返回true,否则返回false

以上描述是针对接受匹配序列的一对迭代器的regex_match重载版本。其余的重载版本都是基于此版本定义的。

相应的regex_search重载版本描述如下:

  

§28.11.3/2 regex_search [re.alg.search]

  Effects: 确定是否存在某个子序列在[first,last)中与正则表达式e匹配。 ... 如果存在这样的序列,则返回true,否则返回false


在您的示例中,如果将regex修改为r {R"(.*?\s\d{2}\s.*)"},则regex_matchregex_search都将成功(但匹配结果不仅是日期,而是整个日期字符串)。

现场演示一个修改过的版本,其中日期被regex_matchregex_search都捕获并显示。


谢谢您的解释。您能否解释一下为什么我们需要将match[0]更改为match[1]以在两种情况下获得精确结果?我的意思是这涉及到std::smatch的使用理解。 - Mantosh Kumar
1
@MantoshKumar 我在日期字段 (\d{2}) 周围添加了括号以创建一个捕获组。根据 match_results 文档match[0] 总是返回整个匹配表达式,而 match[1] 返回第一个子匹配等等。在这种情况下,我们只有一个捕获组,即天数,因此它存储在第一个子匹配中。 - Praetorian
1
从性能角度来看,我敢打赌regex_match比regex_search在计算上平均要快得多,这是由于它能够在匹配失败时立即返回false的能力。相比之下,regex_search将检查子字符串是否与模式匹配,因此在大多数情况下,如果不是所有情况,regex_search都会更慢。因此,在选择这些函数时,请考虑到这一点。 - Steven

21

很简单。 regex_search 查找字符串中是否存在任何部分与正则表达式相匹配的内容。 regex_match 检查整个字符串是否与正则表达式匹配。 作为一个简单的例子,假设有以下字符串:

"one two three four"
如果我使用表达式为"three"regex_search在该字符串上进行搜索,它将成功,因为"three"可以在"one two three four"中找到。
然而,如果我使用regex_match代替,它会失败,因为"three"不是整个字符串,而只是其中的一部分。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接