验证错误

时间:2016-11-05 15:15:24

标签: c++ regex runtime-error

在开发我的个人库时,我偶然发现了我认为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

2 个答案:

答案 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如何匹配一个字面连字符。