boost::regex和std::regex之间的不一致性问题

5

可能重复:
C++11正则表达式无法匹配

以前我使用的是boost::regex来做一些事情,现在我想用std::regex来做一些新东西,但我注意到以下不一致性——所以问题是哪一个是正确的?

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

#include <boost/regex.hpp>

void test(std::string prefix, std::string str)
{
  std::string pat = prefix + "\\.\\*.*?";

  std::cout << "Input   : [" << str << "]" << std::endl;
  std::cout << "Pattern : [" << pat << "]" << std::endl;

  {
    std::regex r(pat);
    if (std::regex_match(str, r))
      std::cout << "std::regex_match: true" << std::endl;
    else
      std::cout << "std::regex_match: false" << std::endl;

    if (std::regex_search(str, r))
      std::cout << "std::regex_search: true" << std::endl;
    else
      std::cout << "std::regex_search: false" << std::endl;
  }

  {
    boost::regex r(pat);
    if (boost::regex_match(str, r))
      std::cout << "boost::regex_match: true" << std::endl;
    else
      std::cout << "boost::regex_match: false" << std::endl;

    if (boost::regex_search(str, r))
      std::cout << "boost::regex_search: true" << std::endl;
    else
      std::cout << "boost::regex_search: false" << std::endl;
  }
}

int main(void)
{
  test("FOO", "FOO.*");
  test("FOO", "FOO.*.*.*.*");
}

对于我来说(gcc 4.7.2,-std=c++11,boost:1.51),我看到如下内容:
Input   : [FOO.*]
Pattern : [FOO\.\*.*?]
std::regex_match: false
std::regex_search: false
boost::regex_match: true
boost::regex_search: true
Input   : [FOO.*.*.*.*]
Pattern : [FOO\.\*.*?]
std::regex_match: false
std::regex_search: false
boost::regex_match: true
boost::regex_search: true

如果我将模式更改为贪婪模式(.*),那么我会看到:
Input   : [FOO.*]
Pattern : [FOO\.\*.*]
std::regex_match: true
std::regex_search: false
boost::regex_match: true
boost::regex_search: true
Input   : [FOO.*.*.*.*]
Pattern : [FOO\.\*.*]
std::regex_match: true
std::regex_search: false
boost::regex_match: true
boost::regex_search: true

该相信哪个?我猜测这里应该是boost正确的?


2
Boost 很可能是正确的选择,因为并不是所有标准库都完全实现了 C++11。正则表达式库似乎是目前最被忽视的,至少在 GCC 中是这样,而在 Visual C++ 中的支持似乎更好。 - Some programmer dude
你所提供的输出不能来自你所提供的程序。你有std::string pat = prefix + "\\.\\*.*?";,因此如果prefixFOO.*,那么pat必须最终成为FOO.*\.\*.*?,而不是FOO.*? - j_random_hacker
@j_random_hacker,是的-抱歉,我刚刚更改了片段中的代码-如果您运行它,您将得到相同的结果。 - Nim
3
GCC的正则表达式库无法使用。不要根据它的行为或不行为得出任何结论。 - Pete Becker
@PeteBecker,谢谢你 - 我想我会继续使用boost::regex... - Nim
正如其他人所指出的那样,Boost是正确的,GCC是完全错误的。您应该在以下网址提交错误报告:http://gcc.gnu.org/bugzilla/。 - Eric Niebler
1个回答

8

当然,gcc不支持 tr1/c++11 正则表达式,但更一般的说法是,根据其文档,boost.regex 的默认值是 perl 5,而 C++ 的默认值是 ECMAScript,扩展了几个与 POSIX BRE 有关的区域设置元素。

具体来说,boost.regex 支持 perl 扩展 在此列出。, 但您没有使用其中任何一个。

现在,我很好奇并通过另外两个编译器运行了您的测试:

来自 clang 的输出:

~ $ clang++ -o test test.cc -std=c++11 -I/usr/include/c++/v1 -lc++ -lboost_regex
~ $ ./test
Input   : [FOO.*]
Pattern : [FOO\.\*.*?]
std::regex_match: true
std::regex_search: true
boost::regex_match: true
boost::regex_search: true
Input   : [FOO.*.*.*.*]
Pattern : [FOO\.\*.*?]
std::regex_match: false
std::regex_search: true
boost::regex_match: true
boost::regex_search: true

来自Visual Studio 2012的输出(不包括boost)

Input   : [FOO.*]
Pattern : [FOO\.\*.*?]
std::regex_match: true
std::regex_search: true
Input   : [FOO.*.*.*.*]
Pattern : [FOO\.\*.*?]
std::regex_match: true
std::regex_search: true

仔细观察clang的差异,在第二个测试中,它将模式[FOO\.\*.*?][FOO.*]匹配,并将[.*.*.*]保持不匹配,这很快就会导致与boost/visual studio不同地匹配[S*?].. 我认为这也是一个错误。

我相信这绝对是一个错误。由于它是经典的扩展正则表达式,您可以使用grep -E轻松检查它,甚至grep也同意boost(grep可以说是最古老的正则表达式引擎之一,并已经被用户彻底滥用/测试)。有趣的是,Microsoft做对了。 - slebetman

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