gcc 4.8 或更早版本对正则表达式有问题吗?
Posted
技术标签:
【中文标题】gcc 4.8 或更早版本对正则表达式有问题吗?【英文标题】:Is gcc 4.8 or earlier buggy about regular expressions? 【发布时间】:2012-09-21 12:13:43 【问题描述】:我正在尝试在 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
.
【问题讨论】:
是 libstdc++ 的<regex>
支持不完整。我们能为您提供什么帮助?
libstdc++中regex
的状态见gcc.gnu.org/onlinedocs/libstdc++/manual/…
说真的,谁认为只提供“返回 false”的 regex_search 实现是个好主意? “哦,我们记录了它”似乎是一种微弱的回答。
@AK4749:这不是错误。它只是完全未实现。尽管这个问题出现的次数令人震惊,特别是因为 libstdc++ <regex>
在过去的 3-4 年中没有任何变化(例如:它仍未实现)。
@KeithThompson,虽然<regex>
是由 libstdc++(GCC 标准库)而不是gcc
(编译器前端)提供的,但它是 GCC(项目)的一部分。见"libstdc++-v3 is developed and released as part of GCC"。如果您的发行版选择将其拆分为与 GCC 无关的单独包。
【参考方案1】:
<regex>
在 GCC 4.9.0 中实现并发布。
在您(旧)版本的 GCC 中,它是 not implemented。
<regex>
原型代码是在 GCC 的所有 C++0x 支持高度实验性时添加的,跟踪早期的 C++0x 草案并可供人们进行实验。这使人们能够在标准定稿之前发现问题并向标准委员会提供反馈。当时很多人很高兴能够在 C++11 完成之前以及许多其他编译器提供 any 支持之前访问最前沿的功能,而这些反馈确实有助于改进 C++11 .这是一件好事TM。
<regex>
代码从未处于有用状态,而是像当时的许多其他代码一样作为正在进行的工作添加。它已签入并可供其他人根据需要进行协作,目的是最终完成。
这通常是开源的工作方式:Release early, release often -- 不幸的是,在<regex>
的情况下,我们只得到了正确的早期部分,而不是通常会完成实施的部分。
库的大部分部分更加完整,现在几乎完全实现了,但 <regex>
还没有实现,所以它自添加以来一直处于未完成状态。
说真的,谁认为提供一个只“返回 false”的 regex_search 实现是个好主意?
几年前这不是一个坏主意,当时 C++0x 仍在进行中,我们发布了许多部分实现。没有人认为它会在这么长时间内无法使用,所以事后看来,也许它应该被禁用并且需要一个宏或内置选项来启用它。但是那艘船很久以前就航行了。 libstdc++.so 库中的导出符号依赖于正则表达式代码,因此简单地删除它(比如在 GCC 4.8 中)并非易事。
【讨论】:
【参考方案2】:特征检测
这是一个 sn-p,用于检测 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
是 defined 在 bits/regex.tcc
在 4.9.x
_GLIBCXX_REGEX_STATE_LIMIT
是 defined 在 bits/regex_automatron.h
在 5+
_GLIBCXX_RELEASE
作为 this answer 的结果被添加到 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
(或其他东西,提示提示微调),则可以更新此 sn-p 以包含它,并且以后的 GCC 版本将与 sn- p 上面。
据我所知,所有其他编译器在 __cplusplus >= 201103L
时都有一个工作 <regex>
但 YMMV。
如果有人在 stdc++-v3
标头之外定义了 _GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT
或 _GLIBCXX_REGEX_STATE_LIMIT
宏,这显然会完全崩溃。
【讨论】:
非常好!我将建议从 GCC 4.9 中的新标头之一检查标头保护宏,但它们没有保护:-\ 对于 GCC 7,宏没有更改,但理论上它们可以为 GCC 做8+,所以请在gcc.gnu.org/bugzilla 提交增强请求,在标题中要求_GLIBCXX_REGEX_IS_OK_NOW_KTHXBAI
之类的内容,这样就不会被遗忘 - 谢谢!
@JonathanWakely 添加了78905。我不知道如何把它变成一个增强错误,但它现在在系统中。【参考方案3】:
此时(在 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
【讨论】:
“此时(在 g++ (GCC) 4.9.2 中使用 std=c++14)仍然不接受 regex_match。” 这不是真的,你是可能用错了。 您的代码不是“一种类似于 regex_match 的方法”,因为该函数尝试匹配子字符串,而不是整个字符串,所以我仍然认为您使用错误。您可以使用std::regex_search
来完成,请参阅wandbox.org/permlink/rLbGyYcYGNsBWsaB以上是关于gcc 4.8 或更早版本对正则表达式有问题吗?的主要内容,如果未能解决你的问题,请参考以下文章
为 iOS 6 或更早版本构建的应用程序能否在 iOS 7 上正常运行?
在 Firefox 60 或更早版本中为 SVG 剪辑路径设置动画时出现随机方块
Linux 下 nodejs 使用官方oracledb库连接数据库 教程
使用 CarPlay 框架的 CarPlay 应用在 iOS 13 或更早版本上崩溃