【问题标题】:C++ program taking minutes to parse large file whereas python is running in a few secondsC ++程序需要几分钟来解析大文件而python在几秒钟内运行
【发布时间】:2015-10-06 00:30:21
【问题描述】:

我在 VS 中运行一个 c++ 程序。我提供了一个正则表达式,我正在解析一个超过 200 万行的文件,用于匹配该正则表达式的字符串。代码如下:

int main() {
    ifstream myfile("file.log");
    if (myfile.is_open())
    {
        int order_count = 0;
        regex pat(R"(.*(SOME)(\s)*(TEXT).*)");
        for (string line; getline(myfile, line);)
        {
            smatch matches;
            if (regex_search(line, matches, pat)) {
                order_count++;
            }
        }
        myfile.close();
        cout << order_count;
    }

    return 0;
}

文件应该搜索匹配的字符串并计算它们的出现次数。我有一个 python 版本的程序,它使用相同的正则表达式在 4 秒内完成此操作。我已经等了大约 5 分钟,上面的 c++ 代码才能工作,但它仍然没有完成。它没有进入无限循环,因为我让它以一定的间隔打印出它的当前行号并且它正在进步。我应该用不同的方式编写上面的代码吗?

编辑:这是在发布模式下运行的。

编辑:这是python代码:

class PythonLogParser:

def __init__(self, filename):
    self.filename = filename

def open_file(self):
    f = open(self.filename)
    return f

def count_stuff(self):
    f = self.open_file()
    order_pattern = re.compile(r'(.*(SOME)(\s)*(TEXT).*)')
    order_count = 0
    for line in f:
        if order_pattern.match(line) != None:
            order_count+=1 # = order_count + 1
    print 'Number of Orders (\'ORDER\'): {0}\n'.format(order_count)
    f.close()

程序终于停止运行。最令人不安的是输出不正确(我知道正确的值应该是什么)。

也许对这个问题使用正则表达式并不是最好的解决方案。如果我找到更好的解决方案,我会更新。

编辑:根据@ecatmur 的回答,我做了以下更改,c++ 程序运行得更快了。

int main() {
        ifstream myfile("file.log");
        if (myfile.is_open())
        {
            int order_count = 0;
            regex pat(R"(.*(SOME)(\s)*(TEXT).*)");
            for (string line; getline(myfile, line);)
            {
                if (regex_match(line, pat)) {
                    order_count++;
                }
            }
            myfile.close();
            cout << order_count;
        }

        return 0;
    }

【问题讨论】:

  • 你在调试模式下运行它吗?
  • 也添加你的python版本。请。你在同一台机器上比较吗? 防病毒软件是否已关闭?
  • 确保您在此处阅读答案:stackoverflow.com/questions/14205096/…
  • 我猜你的 python 版本正在执行 one 读取(在for line in f 它会读取整个文件),而你的 C++ 程序正在执行 ~ 2M 读取(每行一个)。从/向磁盘读取/写入通常很慢,所以我想最好将整个文件内容读取一次,然后逐行解析相应的字符串。
  • 您可以通过每次读取一行来测试 C++ 程序变慢的理论:将 regex_search 替换为仅增加 order_count 的行,并查看是否该程序仍然需要很长时间才能运行。

标签: python c++ regex


【解决方案1】:

您应该使用regex_match,而不是regex_search

7.2.5.3. search() vs. match()

Python 提供了两种不同的基于正则表达式的原始操作:re.match() 仅在字符串的开头检查匹配项,而 re.search() 则检查字符串中任何位置的匹配项

还有:

std::regex_search

regex_search 将成功匹配给定序列的任何子序列,而 std::regex_match 将仅在正则表达式匹配整个序列时返回 true

通过使用regex_search,您将生成n * m 匹配结果,其中n 是搜索字符串中心部分之前的字符数,m 是搜索字符串中心部分之后的字符数。毫不奇怪,这需要很长时间才能生成。

事实上,更有效的方法是使用regex_search,但与搜索字符串的中心部分一起使用:

    regex pat(R"((SOME)(\s)*(TEXT))");

并使用regex_search 的重载,它不会将匹配结果带出参数(因为您忽略了匹配结果):

        if (regex_search(line, pat)) {    // no "matches"
            order_count++;
        }

【讨论】:

  • C++ regex_constants::match_continuous 也可能有助于模仿 python 匹配——我这里的 python 有点模糊。
  • 在进行更改后比 regex_search 工作得快得多,但是,即使我在 c++ 和 python 中使用相同的正则表达式,输出仍然不正确。 c++解释正则表达式的方式和python解释正则表达式的方式有区别吗?
  • @JeremyFisher 哦,很多;默认的 C++ 正则表达式语法是 Modified ECMAScript,它非常接近 Javascript 语法:en.cppreference.com/w/cpp/regex/ecmascript;同时 Python 有自己的语法:docs.python.org/2/library/re.html#regular-expression-syntax - 你必须仔细研究他们在你的模式上存在分歧的地方。
  • @JeremyFisher:将\s 更改为\\s。要总体改进您的模式,请避免创建无用的捕获组。 (\s)* => \s*
  • @CasimiretHippolyte 他使用的是原始文字,所以我不认为双重转义 \s 是必要的。
猜你喜欢
  • 2014-04-12
  • 2019-08-03
  • 1970-01-01
  • 2014-10-18
  • 1970-01-01
  • 1970-01-01
  • 2012-07-14
  • 2019-08-05
  • 2021-02-05
相关资源
最近更新 更多