gcc 4.8或更早的关于正则表达式的错误吗?


101

我正在尝试在C ++ 11的一段代码中使用std :: regex,但是似乎该支持有点问题。一个例子:

#include <regex>
#include <iostream>

int main (int argc, const char * argv[]) {
    std::regex r("st|mt|tr");
    std::cerr << "st|mt|tr" << " matches st? " << std::regex_match("st", r) << std::endl;
    std::cerr << "st|mt|tr" << " matches mt? " << std::regex_match("mt", r) << std::endl;
    std::cerr << "st|mt|tr" << " matches tr? " << std::regex_match("tr", r) << std::endl;
}

输出:

st|mt|tr matches st? 1
st|mt|tr matches mt? 1
st|mt|tr matches tr? 0

使用gcc(MacPorts gcc47 4.7.1_2)4.7.1编译时

g++ *.cc -o test -std=c++11
g++ *.cc -o test -std=c++0x

要么

g++ *.cc -o test -std=gnu++0x

此外,如果我只有两种替代模式,则正则表达式可以很好地工作,例如 st|mt,,因此由于某些原因,看起来最后一个不匹配。该代码可与Apple LLVM编译器很好地配合。

关于如何解决此问题的任何想法?

更新资料一种可能的解决方案是使用组来实现多个替代方案,例如(st|mt)|tr


9
是的,libstdc ++的<regex>支持不完整。我们能为您提供什么帮助?
kennytm 2012年

10
对于状态regex中的libstdc ++,见gcc.gnu.org/onlinedocs/libstdc++/manual/...
ecatmur

51
认真地说,谁提供了只返回“ false”的regex_search实现的一个好主意?“哦,我们记录了下来”似乎有点虚弱。
Paul Rubel 2012年

4
@ AK4749:这不是错误。完全没有实现。尽管出现此问题的次数令人震惊,尤其是由于libstdc ++ <regex>在过去3-4年中没有发生任何变化(例如:它尚未实现)。
rubenvb 2012年

5
@KeithThompson,虽然确实<regex>是libstdc ++(GCC标准库)提供的,而不是gcc(编译器前端)提供的,但它是GCC(项目)的一部分。请参见“ libstdc ++-v3是作为GCC的一部分开发和发行的”。如果您的发行版选择将其拆分为单独的程序包,则与GCC无关。
乔纳森·

Answers:


168

<regex> 已在GCC 4.9.0中实施并发布。

在您的(旧)GCC版本中,未实现

<regex>当GCC对C ++ 0x的所有支持都处于高度实验性,跟踪早期C ++ 0x草案并可供人们进行实验时,添加了该原型代码。这使人们能够在标准最终确定之前发现问题并向标准委员会提供反馈。当时,很多人很高兴能够在C ++ 11完成之前和许多其他编译器提供任何支持之前就获得了最先进的功能,而这些反馈确实有助于改善C ++ 11。这是一件好事TM

<regex>代码从来没有处于有用状态,但是与当时的许多其他代码一样,它是作为一个进行中的工作而添加的。它已签入,并在其他人愿意的情况下可供其他人协作,以期最终完成。

开源通常是这样工作的:提前发布,经常发布 -不幸的是,在<regex>我们只正确地使用了早期部分而不是完成实施的通常部分的情况下。

库的大多数部分都比较完整,现在几乎已完全实现,但是<regex>还没有完全实现,因此自添加以来,它一直处于未完成的状态。

认真地说,谁提供了只返回“ false”的regex_search实现的一个好主意?

几年前,C ++ 0x仍在开发中,并且交付了许多部分实现,这并不是一个坏主意。没有人认为它会这么长时间不可用,因此事后看来,也许应该禁用它,并且需要使用宏或内置时间选项才能启用它。但是那艘船早就航行了。从libstdc ++。so库中导出的符号依赖于正则表达式代码,因此简单地将其删除(例如,在GCC 4.8中)并不是一件容易的事。


12

特征检测

这是一个代码片段,用于检测是否libstdc++使用C预处理程序定义实现:

#include <regex>
#if __cplusplus >= 201103L &&                             \
    (!defined(__GLIBCXX__) || (__cplusplus >= 201402L) || \
        (defined(_GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT) || \
         defined(_GLIBCXX_REGEX_STATE_LIMIT)           || \
             (defined(_GLIBCXX_RELEASE)                && \
             _GLIBCXX_RELEASE > 4)))
#define HAVE_WORKING_REGEX 1
#else
#define HAVE_WORKING_REGEX 0
#endif

巨集

  • _GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT定义bits/regex.tcc4.9.x
  • _GLIBCXX_REGEX_STATE_LIMIT定义bits/regex_automatron.h5+
  • _GLIBCXX_RELEASE7+由于此答案而被添加到GCC主要版本中

测试中

您可以使用GCC进行测试,如下所示:

cat << EOF | g++ --std=c++11 -x c++ - && ./a.out
#include <regex>

#if __cplusplus >= 201103L &&                             \
    (!defined(__GLIBCXX__) || (__cplusplus >= 201402L) || \
        (defined(_GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT) || \
         defined(_GLIBCXX_REGEX_STATE_LIMIT)           || \
             (defined(_GLIBCXX_RELEASE)                && \
             _GLIBCXX_RELEASE > 4)))
#define HAVE_WORKING_REGEX 1
#else
#define HAVE_WORKING_REGEX 0
#endif

#include <iostream>

int main() {
  const std::regex regex(".*");
  const std::string string = "This should match!";
  const auto result = std::regex_search(string, regex);
#if HAVE_WORKING_REGEX
  std::cerr << "<regex> works, look: " << std::boolalpha << result << std::endl;
#else
  std::cerr << "<regex> doesn't work, look: " << std::boolalpha << result << std::endl;
#endif
  return result ? EXIT_SUCCESS : EXIT_FAILURE;
}
EOF

结果

这是各种编译器的一些结果:


$ gcc --version
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-11)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ ./a.out
<regex> doesn't work, look: false

$ gcc --version
gcc (GCC) 6.2.1 20160830
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ ./a.out
<regex> works, look: true

$ gcc --version
gcc (Debian 4.9.2-10) 4.9.2
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ ./a.out
<regex> works, look: true

$ gcc --version
gcc (Ubuntu 6.2.0-5ubuntu12) 6.2.0 20161005
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ ./a.out
<regex> works, look: true

$ gcc --version
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ ./a.out
<regex> works, look: true

$ gcc --version
gcc (GCC) 6.2.1 20160830
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ clang --version
clang version 3.9.0 (tags/RELEASE_390/final)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
$ ./a.out  # compiled with 'clang -lstdc++'
<regex> works, look: true

这是龙

这是完全不受支持的,并且依赖于对GCC开发人员已放入bits/regex*标头中的私有宏的检测。他们可以改变,走在任何时间。希望它们不会在当前的4.9.x,5.x,6.x版本中删除,但可以在7.x版本中删除。

如果GCC开发人员添加了 #define _GLIBCXX_HAVE_WORKING_REGEX 1在持续存在的7.x版本中(或某些提示提示,则轻推一下),则此代码段可以进行更新以包括该代码段,以后的GCC版本将与上述代码段一起使用。

据我所知,所有其他的编译器有一个工作<regex>__cplusplus >= 201103L,但情况因人而异。

显然,如果有人在标头之外定义_GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT_GLIBCXX_REGEX_STATE_LIMIT宏,则这将完全中断stdc++-v3


非常好!我打算建议从GCC 4.9中新的标头之一中检查标头保护宏,但是它们没有保护:-\宏对于GCC 7并没有改变,但是理论上它们可以对GCC进行8岁以上,因此请在gcc.gnu.org/bugzilla提出增强功能请求岁以上要求_GLIBCXX_REGEX_IS_OK_NOW_KTHXBAI在标题中提供类似内容,这样就不会被忘记-谢谢!
Jonathan Wakely

1
@JonathanWakely添加了 78905。我不确定如何使它成为增强错误,但现在已经在系统中。
马特·克拉克森

1

目前(在g ++(GCC)4.9.2中使用std = c ++ 14)仍不接受regex_match。

这是一种类似于regex_match的方法,但改用sregex_token_iterator。它可以与g ++一起使用。

string line="1a2b3c";
std::regex re("(\\d)");
std::vector<std::string> inVector{
    std::sregex_token_iterator(line.begin(), line.end(), re, 1), {}
};

//prints all matches
for(int i=0; i<inVector.size(); ++i)
    std::cout << i << ":" << inVector[i] << endl;

它将打印1 2 3

您可以在以下位置阅读sregex_token_iterator参考:http ://en.cppreference.com/w/cpp/regex/regex_token_iterator


1
“目前(在g ++(GCC)4.9.2中使用std = c ++ 14)仍不接受regex_match。” 事实并非如此,您可能错误地使用了它。
乔纳森·韦克利

1
您的代码不是“类似于regex_match的方法”,因为该函数尝试匹配子字符串,而不是整个字符串,因此我仍然认为您使用的是错误的。您可以用它来做std::regex_search,请参阅wandbox.org/permlink/rLbGyYcYGNsBWsaB
Jonathan Wakely
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.