【问题标题】:Difference between regex_match and regex_search?regex_match 和 regex_search 之间的区别?
【发布时间】:2012-07-24 09:35:44
【问题描述】:

我正在尝试使用正则表达式来尝试对 this question 做出回答,并发现虽然 regex_match 找到了匹配项,但 regex_search 却没有。

以下程序是用g++ 4.7.1编译的:

#include <regex>
#include <iostream>

int main()
{
    const std::string s = "/home/toto/FILE_mysymbol_EVENT.DAT";
    std::regex rgx(".*FILE_(.+)_EVENT\\.DAT.*");
    std::smatch match;

    if (std::regex_match(s.begin(), s.end(), rgx))
        std::cout << "regex_match: match\n";
    else
        std::cout << "regex_match: no match\n";

    if (std::regex_search(s.begin(), s.end(), match, rgx))
        std::cout << "regex_search: match\n";
    else
        std::cout << "regex_search: no match\n";
}

输出:

正则表达式匹配:匹配 regex_search: 不匹配

我的假设是两者都应该匹配错误,还是 GCC 4.7.1 中的库有问题?

【问题讨论】:

  • GCC 的正则表达式库在很大程度上仍未实现(GCC Y U SHIP BROKEN &lt;regex&gt;?),所以我倾向于说,是的,这是库的问题。
  • 您的程序与 VS2010 产生了两次匹配,所以我猜问题出在 gcc 使用的库上。您是否尝试过使用正则表达式库的 boost 版本?
  • @H2CO3 您也可以使用汇编,但您可能不想这样做 :) C++ 中包含的 C 函数也是如此。它们打破了 C++ 编程风格(例如,您需要开始检查返回码,而不是关心异常)。
  • @H2CO3 当然可以,但目前我正在尝试了解新的 C++11 标准及其所有功能。在现实世界的场景中,我可能会使用 Boost,或者系统中可用的任何东西(例如标准 POSIX 功能)。
  • @H2CO3 :) 如果我需要在实际代码中实现类似的东西,我肯定会使用 POSIX 正则表达式(或 Boost.Regex)。但是OP的问题是一个很好的问题。实际上我想知道为什么 GCC 决定发布一个损坏的正则表达式实现。完全没有支持总比坏了好...

标签: c++ regex gcc g++


【解决方案1】:

假设C++和Boost Regex具有相似的结构和功能,那么regex_matchregex_search的区别解释here

regex_match() 算法只会在正则表达式的情况下报告成功 从头到尾匹配整个输入。如果正则表达式匹配 只有一部分输入,regex_match() 将返回 false。如果你想 搜索字符串以查找正则表达式的子字符串 匹配,使用regex_search() 算法。

【讨论】:

    【解决方案2】:

    您的正则表达式 工作正常(两者都匹配,这是正确的)在 VS 2012rc 中。

    在 g++ 4.7.1 (-std=gnu++11) 中,如果使用:

    • ".*FILE_(.+)_EVENT\\.DAT.*"regex_match 匹配,但 regex_search 不匹配。
    • ".*?FILE_(.+?)_EVENT\\.DAT.*"regex_matchregex_search 都不匹配 (O_o)。

    所有变体都应该匹配,但有些不匹配(原因已由 betabandido 指出)。在 g++ 4.6.3 (-std=gnu++0x) 中,行为与 g++ 4.7.1 相同。

    Boost (1.50) 正确匹配所有内容 两种模式变体。

    总结

    正则表达式匹配正则表达式搜索 -------------------------------------------------- --- g++ 4.6.3 linux OK/- - g++ 4.7.1 linux OK/- - 与 2010 年相比 好的 好的 vs 2012rc OK OK 提升 1.50 胜利 OK OK boost 1.50 linux OK OK -------------------------------------------------- ---

    关于你的模式,如果你意思是一个点字符'.',那么你应该这样写("\\.")。您还可以通过使用非贪婪修饰符 (?) 来减少回溯:

    ".*?FILE_(.+?)_EVENT\\.DAT.*"
    

    【讨论】:

      【解决方案3】:

      翻阅最新的libstdc++ source code for regex_search,你会发现:

      * @todo Implement this function.
      

      很遗憾,这不是剩下的唯一 TODO 项。 GCC 的&lt;regex&gt; 实现目前不完整。我建议在 GCC 赶上之前使用 Boost 或 Clang 和 #ifdef 代码。

      (这在 4.8 分支中都没有修复。)

      【讨论】:

        【解决方案4】:

        我尝试在 C++11 中使用正则表达式库,但遇到了很多问题(使用 g++ 4.6 和 4.7)。基本上,要么没有支持,要么只有部分支持。即使是 SVN 版本也是如此。这里有一个描述current status for the SVN version of libstdc++ 的链接。

        所以,就目前而言,我想最好的选择是继续使用Boost.Regex

        或者,您可以尝试使用libc++。根据this document,对正则表达式的支持已经完成。

        【讨论】:

        • clang 是编译器,而不是标准库 - 我认为您的意思是使用 libc++
        • @JonathanWakely 确实。我以前从未使用过 libc++,所以我认为它是 clang 的一部分。感谢您指出这一点。
        • 它们都是 LLVM 项目的一部分
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-25
        • 2020-05-10
        • 2014-09-20
        • 2010-10-28
        • 2015-10-04
        相关资源
        最近更新 更多