【问题标题】:C++ regular expression over a stream流上的 C++ 正则表达式
【发布时间】:2016-01-21 22:05:55
【问题描述】:

我有一个非常大的文本文件(最多几百 MB),我想用 STL 正则表达式处理它。我正在寻找的匹配区域跨越几行,并且在文件中至少出现了几千次。

我可以为此目的使用流迭代器吗?我试过std::istream_iterator<char>,但没有运气。有人可以发布一个最小的工作示例吗?

请注意,我正在寻找仅涉及 STL 的解决方案。在完美的解决方案中,我想遍历所有匹配项。

编辑

阅读评论后,我明白这是不可能的。因此,也许还有另一种方法可以迭代在大文本文件中找到的正则表达式匹配:

#include <regex>
#include <iostream>
#include <string>

const std::string s = R"(Quick brown fox
jumps over
several lines)"; // At least 200MB of multiline text here

int main(int argc,char* argv[]) {

    std::regex find_jumping_fox("(Quick(?:.|\\n)+?jump\\S*?)");
    auto it = std::sregex_iterator(s.begin(), s.end(),        find_jumping_fox);

    for (std::sregex_iterator i = it; i != std::sregex_iterator(); ++i) {
        std::smatch match = *i;                                                 
        std::string match_str = match.str(); 
        std::cout << match_str << '\n';
    }  
}

【问题讨论】:

  • “我可以使用流迭代器吗”——简单的回答:不。正则表达式匹配需要双向迭代器。这也不是一个任意的限制。最好的办法是找到一个通过内部缓存将流迭代器适配为双向迭代器的类。但是,标准库不提供此功能。甚至istreambuf_iterator 也只是一个输入迭代器。
  • 如果您发布示例代码会有所帮助,即使它实际上并没有工作。我的意思是,只是一个带有几行代码的main 函数,例如尝试使用std::istream_iterator。这将有助于确保其他人正确理解您的问题。
  • 为什么我们需要遍历输入? std::regex_match的匹配结果已经是一个序列了。
  • 我认为现在 0.2GB 的字符串并不是那么大。如果地址空间无法容纳(超过 2GB?),就会出现真正的问题。
  • @9dan:如果您实际上不需要,200MB 是要加载到内存中的大量数据。我真的希望程序停止这样做只是因为“人们有很多 RAM”!

标签: regex c++11 iterator


【解决方案1】:

您无法在流上进行匹配,因为匹配失败意味着什么?正则表达式的开头是否匹配并且需要流式传输更多字符,或者流的任何部分都没有匹配。

但是在您编辑之后,我们可以在字符串上找到偏移量和匹配范围。你会想要使用:

const vector<smatch> foo = { sregex_iterator(cbegin(s), cend(s), find_jumping_fox), sregex_iterator() }

这里有详细解释:https://topanswers.xyz/cplusplus?q=729#a845

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-18
    相关资源
    最近更新 更多