繁体   English   中英

正则表达式在g ++ 4.9下匹配,但在g ++-5.3.1下失败

[英]Regex matches under g++ 4.9 but fails under g++-5.3.1

我用正则表达式标记字符串; 这在g++-4.9下正常工作,但在g++-5.3.1下失败。

我有以下txt文件:

0001-SCAND ==> "Scandaroon" (from Philjumba)
0002-KINVIN ==> "King's Vineyard" (from Philjumba)
0003-HANNI ==> "Hannibal: Rome vs. Carthage" (from Philjumba)
0004-LOX ==> "Lords of Xidit" (from Philjumba)

我使用正则表达式,空格,引号对和括号对对进行标记。 例如,第一行应如下标记:

0001-SCAND
==>
"Scandaroon"
(from Philjumba)

我写了以下std::regex

std::regex FPAT("(\\S+)|(\"[^\"]*\")|(\\([^\\)]+\\))";

我用以下方式标记字符串:

std::vector<std::string>
split( const std::string & input, const std::regex & regex ) {

        std::sregex_token_iterator
                first{input.begin(), input.end(), regex, 0},
                last;

        return {first, last};
}

这将返回匹配项。 g++-4.9该字符串按要求进行标记,但在g++-5.3.1下,该字符串的标记如下:

0001-SCAND
==>
"Scandaroon"
(from
Philjumba)

或第三行标记如下:

0003-HANNI
==>
"Hannibal:
Rome
vs.
Carthage"
(from
Philjumba)

可能是什么问题?


编辑:我正在调用该函数,如下所示:

std::string line("0001-SCAND ==> \"Scandaroon\" (from Philjumba)");
auto elems = split( line, FPAT );

编辑:根据@xaxxon的反馈,我用向量替换了返回迭代器,但在g++-5.3下仍然无法正常工作。

std::vector<std::string>
split( const std::string & input, const std::regex & regex ) {

        std::sregex_token_iterator
                first{input.begin(), input.end(), regex, 0},
                last;

        std::vector< std::string > elems;
        elems.reserve( std::distance(first,last) );

        for ( auto it = first; it != last; ++ it ) {
                //std::cout << (*it) << std::endl;
                elems.push_back( *it );
        }

        return elems;
}

正则表达式很渴望

因此,对于正则表达式"Set|SetValue"和文本"SetValue" ,regex创建"Set"

您必须仔细选择订单:

std::regex FPAT(R"(("[^\"]*\")|(\([^\)])+\)|(\S+))");

最后考虑\\S+

另一种选择是不使用默认选项(请参阅http://en.cppreference.com/w/cpp/regex/syntax_option_type ),并使用std::::regex::extended

std::regex FPAT(R"((\S+)|("[^\"]*\")|(\([^\)])+\))", std::::regex::extended);

因此,看来g ++-5.3.1已修复了自g ++-4.9以来的一个错误。

您发布的信息不足以让我确定(您更新了它,显示您正在使用左值调用它,因此,该信息可能与您无关,但除非有人要我取下它,否则我将其保留) ,但是如果您按照我的方式进行操作,则会忘记迭代器已放入源字符串中,并且该字符串不再有效。

您可以从input删除const ,但是能够在其中放置右值非常方便,所以.....

为避免这种情况,我会采取以下措施-我向一个看起来像结果的东西返回一个unique_ptr,但是我将实际的源字符串和它一起隐藏了,这样在我完成使用之前,字符串不会消失。 这可能是UB,但我认为它几乎可以一直工作:

// Holds a regex match as well as the original source string so the matches remain valid as long as the 
// caller holds on to this object - but it acts just like a std::smatch
struct MagicSmatch {
    std::smatch match;
    std::string data;

    // constructor makes a copy of the string and associates
    // the copy's lifetime with the iterators into the string (the smatch)
    MagicSmatch(const std::string & data) : data(data)
    {}
};

// this deleter knows about the hidden string and makes sure to delete it
// this cast is probably UB because std::smatch isn't a standard layout type
struct MagicSmatchDeleter {
    void operator()(std::smatch * smatch) {
        delete reinterpret_cast<MagicSmatch *>(smatch);
    }
};


// the caller just thinks they're getting a smatch ptr.. but we know the secret
std::unique_ptr<std::smatch, MagicSmatchDeleter> regexer(const std::regex & regex, const std::string & source)
{
    auto magic_smatch = new MagicSmatch(source);
    std::regex_search(magic_smatch->data, magic_smatch->match, regex);
    return std::unique_ptr<std::smatch, MagicSmatchDeleter>(reinterpret_cast<std::smatch *>(magic_smatch));

}

只要将其称为auto results = regexer(....),它就很容易使用,尽管results是一个指针,而不是适当的smatch ,因此[]语法效果不佳。

暂无
暂无

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

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