在开发我的个人库时,我偶然发现了我认为libstdc ++ 6中的错误。
因为我非常肯定这个图书馆已经被很多技术高超的人审阅过,所以我来这里是为了验证我的发现并获得进一步帮助。
请考虑以下代码:
#include <regex>
#include <iostream>
int main()
{
std::string uri = "http://example.com/test.html";
std::regex reg(...);
std::smatch match;
std::regex_match(uri, match, reg);
for(auto& e: match)
{
std::cout<<e.str() <<std::endl;
}
}
我写了一个正则表达式来解析URL到
我使用了以下正则表达式(在c ++中):
std::regex reg("^(.+):\\/\\/(.+@)?([a-zA-Z\\.\\-0-9]+)(:\\d{1,5})?([^?\\n\\#]*)(\\?[^#\\n]*)?(\\#.*)?$");
这在在线测试人员和MSVC ++ 2015 Update 3中运行良好,但在我的构建主机上失败,其中主机部分与主机和路径匹配。
Buildhost:
g ++(Ubuntu 5.4.0-6ubuntu1~16.04.2)5.4.0 20160609
libstdc ++ 6:amd64 5.4.0-6ubuntu1~16.04.2
我认为这是一个错误,因为如果我将正则表达式更改为:
std::regex reg("^(.+):\\/\\/(.+@)?([a-zA-Z\\.0-9\\-]+)(:\\d{1,5})?([^?\\n\\#]*)(\\?[^#\\n]*)?(\\#.*)?$");
它的工作原理很好,它的行为应该完全一样。
失败的正则表达式:https://ideone.com/7n2JdK
工作正则表达式:https://ideone.com/6NMPUW
我是否想念一些非常重要的内容,或者这是libstdc ++ 6中的错误?
唯一的区别在于char类:
[a-zA-Z\\.\\-0-9] // not working
[a-zA-Z\\.0-9\\-] // working
答案 0 :(得分:0)
这显然是一个错误,因为"[.\\-0]"
应该被解析为匹配.
或-
字符的字符类(因为连字符是用文字{{1}转义的}}或\
。由于未知原因,连字符被解析为范围运算符,0
子表达式等于[a-zA-Z\\.\\-0-9]+
。请参阅this regex demo。
第二个表达式有效,因为字符类末尾(及其开头)的[a-zA-Z.-0-9]+
始终被解析为文字连字符。
同一个错误的另一个例子:
-
std::string uri = "%";
std::regex reg(R"([$\-&])");
std::smatch match;
std::regex_match(uri, match, reg);
for(auto& e: match)
{
std::cout<< e.str() <<std::endl;
}
正则表达式不应与[$\-&]
匹配,它应与%
,$
或-
匹配,但无论出于何种原因,{{1} (在ASCII表格中&
和%
之间)is still matched。
答案 1 :(得分:0)
我觉得这不是错误,但我认为这与基本的RE规范有关。
如果想要匹配这样的事情,应该了解文字-
(连字符),尤其是的细节。 Quoth re_format(7)
(第一句):
包含文字
-
,使其成为范围的第一个或最后一个字符,或第二个端点。使用文字-
作为第一个结尾 - 范围点,将其括在[.
和.]
中,使其成为整理元素(见下文)。除了 这些以及使用[
的一些组合(请参阅下一段),所有其他特殊字符(包括\
)都会丢失 括号表达式中的特殊意义。
即。转义一个连字符并期望它匹配为一个字符,这正是man page sais如何匹配一个字面连字符。