繁体   English   中英

gcc 4.8 或更早版本是否有关于正则表达式的错误?

[英]Is gcc 4.8 or earlier buggy about regular expressions?

我试图在一段 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

<regex>在 GCC 4.9.0 中实现和发布。

在您(旧)版本的 GCC 中,它没有实现

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

<regex>代码从未处于有用状态,而是像当时的许多其他代码一样作为正在进行的工作添加。 它被签入并提供给其他人,如果他们愿意,可以进行协作,目的是最终完成。

这通常是开源的工作方式:早发布,经常发布——不幸的是,在<regex>的情况下,我们只得到了早期的部分,而不是完成实施的经常部分。

库的大部分内容更加完整,现在几乎完全实现,但<regex>没有实现,所以它自添加以来一直处于未完成状态。

不过说真的,谁认为发布一个只执行“返回假”的 regex_search 实现是个好主意?

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

特征检测

这是一个片段,用于检测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_LIMIT5+中的bits/regex_automatron.h定义
  • 由于此答案_GLIBCXX_RELEASE已添加到7+并且是 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 开发人员在持续存在的 7.x 版本中添加了#define _GLIBCXX_HAVE_WORKING_REGEX 1 (或其他东西,提示提示轻推轻推),则可以更新此代码段以包含该代码段,并且以后的 GCC 版本将与上述代码段一起使用。

据我所知,当__cplusplus >= 201103L但 YMMV 时,所有其他编译器都有一个有效的<regex>

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

此时(在 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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM