【问题标题】:How to speed up regex searching for large quantity of potentially large files in C++?如何加快正则表达式在 C++ 中搜索大量潜在大文件的速度?
【发布时间】:2019-08-31 21:53:02
【问题描述】:

我正在尝试编写一个程序来使用 Excel 文档作为配置文件来读取用户输入的通配符文件和通配符字符串。例如,用户可以在 C:\Read*.txt 中输入,C 盘中任何以 Read 开头的文件,然后是读取后的任何字符,并且是文本文件,都将包含在搜索中。

他们可以搜索 Message: * 并且所有以“Message:”开头并以任何字符序列结尾的字符串都会被匹配。

到目前为止它是一个工作程序,但问题是速度效率非常糟糕,我需要它能够搜索非常大的文件。我正在使用文件流和正则表达式类来执行此操作,但我不确定是什么花费了这么多时间。

我的代码中的大部分时间都花在了以下循环中(我只包含了 while 循环上方的行,以便您更好地理解我要做什么):

smatch matches;
vector<regex> expressions;

for (int i = 0; i < regex_patterns.size(); i++){expressions.emplace_back(regex_patterns.at(i));}

auto startTimer = high_resolution_clock::now();
// Open file and begin reading
ifstream stream1(filePath);
if (stream1.is_open())
{
    int count = 0;
    while (getline(stream1, line))
    {
        // Continue to next step if line is empty, no point in searching it.
        if (line.size() == 0)
        {
            // Continue to next step if line is empty, no point in searching it.
            continue;
        }

        // Loop through each search string, if match, save line number and line text,
        for (int i = 0; i < expressions.size(); i++)
        {
            size_t found = regex_search(line, matches, expressions.at(i));
            if (found == 1)
            {
                lineNumb.push_back(count);
                lineTextToSave.push_back(line);
            }
        }
        count = count + 1;
    }
}
auto stopTimer = high_resolution_clock::now();
auto duration2 = duration_cast<milliseconds>(stopTimer - startTimer);
cout << "Time to search file: " << duration2.count() << "\n";

还有比这更好的搜索文件的方法吗?我尝试查找了很多东西,但没有找到迄今为止我理解的程序示例。

【问题讨论】:

  • 请注意,您所描述的不是正则表达式,而是globbing
  • 也许看看这里:根据 ripgrep,这个问题的答案'有限自动机'github.com/BurntSushi/ripgrep
  • @Someprogrammerdude 这是一种更通用的正则表达式形式。您是否想将其称为通配符或正则表达式并不重要。该程序按预期工作,只是不够快。我使用的正则表达式是“globs”的形式,如果你想这样称呼的话。
  • 考虑使用更快的正则表达式引擎,特别是可以同时匹配多个正则表达式的引擎。例如,RE2:github.com/google/re2/blob/master/re2/set.h#L23

标签: c++ regex string file search


【解决方案1】:

按优先顺序排列的一些想法:

  1. 您可以将所有正则表达式模式连接在一起以形成单个正则表达式,而不是在每行上匹配 r 正则表达式。这将使您的程序加速r。示例:(R1)|(R2)|(...)|(Rr)

  2. 确保在使用前编译正则表达式。

  3. 不要将最后的 .* 添加到您的正则表达式模式中。

一些想法,但不可移植:

  1. 内存映射文件而不是通过 iostreams 读取
  2. 考虑是否值得重新实现grep 而不是通过popen() 调用grep

【讨论】:

  • 你能告诉我一个使用内存映射的例子吗?我看过的所有地方基本上都告诉我要使用它来制作最有效的文件读取代码,但我不明白如何以编程方式实现它。我对 C++ 很陌生,所以这可能是其中的一部分,但仍然如此。即使有我面前的资源,我也不知道如何使用这种方法,主要是因为它们没有解释任何东西。
猜你喜欢
  • 2017-01-17
  • 2011-12-24
  • 2020-09-24
  • 2013-07-14
  • 1970-01-01
  • 2012-03-14
  • 1970-01-01
  • 1970-01-01
  • 2015-05-31
相关资源
最近更新 更多