std::regex_match 和 std::regex_search 之间的区别?

Posted

技术标签:

【中文标题】std::regex_match 和 std::regex_search 之间的区别?【英文标题】:Difference between std::regex_match & std::regex_search? 【发布时间】:2014-11-02 05:06:59 【问题描述】:

已编写以下程序以使用 C++11 std::regex_match 和 std::regex_search 获取“日”信息。但是,使用第一种方法返回false,第二种方法返回true(预期)。我阅读了与此相关的文档和已经存在的 SO 问题,但我不明白这两种方法之间的区别以及我们应该何时使用它们中的任何一种?对于任何常见问题,它们可以互换使用吗?

Difference between regex_match and 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  rR"(\s\d2\s)";
    //std::regex  r"\\s\\d2\\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.

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

【问题讨论】:

【参考方案1】:

regex_match 仅在匹配整个输入序列时返回true,而regex_search 将成功,即使只有一个子序列匹配regex

引自 N3337,

§28.11.2/2 regex_match [re.alg.match]效果: 确定是否正则表达式 e所有字符序列 [first,last) 之间存在匹配。 ... 如果存在这样的匹配则返回true,否则返回false

上面的描述是针对regex_match 重载的,它需要一对迭代器来匹配要匹配的序列。其余的重载都是根据这个重载来定义的。

对应的regex_search重载描述为

§28.11.3/2 regex_search [re.alg.search]效果: 确定是否在[first,last)中有一些子序列匹配正则表达式e... 如果存在这样的序列,则返回 true,否则返回 false


在您的示例中,如果您将regex 修改为rR"(.*?\s\d2\s.*)";regex_matchregex_search 都会成功(但匹配结果不仅仅是日期,而是整个日期字符串)。

Live demo 您的示例的修改版本,其中regex_matchregex_search 都捕获并显示了这一天。

【讨论】:

感谢您的解释。您能否解释一下为什么我们需要从 match[0] 更改为 match[1] 以获得两种情况下的确切结果?我的意思是它是关于 std::smatch 使用理解。 @MantoshKumar 我在日期字段(\d2) 周围添加了括号以创建捕获组。从match_resultsdocumentation,match[0] 总是返回整个匹配的表达式,而match[1] 返回第一个子匹配等等。在这种情况下,我们当天只有一个捕获组,因此存储在第一个子匹配中。 从性能的角度来看,我敢打赌 regex_match 在计算上比 regex_search 平均要快得多,因为它能够在匹配失败时立即返回 false。相反,regex_search 将检查子字符串是否与模式匹配,因此在大多数情况下,如果不是所有情况,regex_search 会更慢。因此,在这些功能之间进行选择时要考虑到这一点。【参考方案2】:

这很简单。 regex_search 查看字符串以查找字符串的任何部分是否与正则表达式匹配。 regex_match 检查整​​个字符串是否与正则表达式匹配。作为一个简单的例子,给定以下字符串:

"one two three four"

如果我在该字符串上使用regex_search 和表达式"three",它将成功,因为"three" 可以在"one two three four" 中找到

但是,如果我改用regex_match,它将失败,因为"three" 不是整个字符串,而只是其中的一部分。

【讨论】:

以上是关于std::regex_match 和 std::regex_search 之间的区别?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 std::regex_match 会产生不同的结果

正则表达式

std::reference_wrapper<std::any> 上的类型特征

std::regexC++文件路径正则表达式

在matlab中R = random('Normal',0,1,2,4): 生成期望为 0,标准差为 1 的(2 行 4 列)2× 4 个正态随机数

如何检查字符串是不是以回文开头?