QRegularExpression惰性匹配不适用于非常大的字符串

时间:2018-10-25 03:34:07

标签: regex qt qt5 pcre qregularexpression

我正在Qt 5.10.1中使用QRegularExpression从由页眉和页脚绑定的文件中提取文本部分。例如,考虑以下文本:

...
begin
    some text
    some more text
    ...
end
...
begin
    etc.

然后我将使用以下正则表达式捕获一段文本:

^begin\n([\s\S]+?)^end

这里没有什么不寻常的。问题是如果文本部分很大(超过100k行),则正则表达式将停止产生匹配项。我在其他文本编辑器(TextPad)中尝试了搜索,并且搜索效果很好,因此我怀疑这是由于QRegularExpression中存在某种MAX_SIZE常量或更可能是它使用的PCRE2库引起的。但是我不知道在哪里看或者这是否可以调整?也许这被认为是错误?

下面是一些可用于演示我的问题的代码。对我来说,它的爆炸速度为100,000行(10,000,000字节)。

QString s = "This line of text is exactly one hundred bytes long becuase it's a nice round number for this test.\n";
QRegularExpression re = QRegularExpression(R"(^begin\n([\s\S]+?)^end)", QRegularExpression::MultilineOption);
qDebug() << "start check:";
for (int i=10000; i<200000; i=i+1000) {
    QString test = "begin\n" + s.repeated(i) + "end\n";
    QRegularExpressionMatch match = re.match(test);
    if (!match.hasMatch()) {
        qDebug() << "lazy match failed - trying greedy match";
        re.setPattern(R"(^begin\n([\s\S]+)^end)");
        QRegularExpressionMatch match = re.match(test);
        qDebug() << match.hasMatch();
        break;
    }
    qDebug() << i;
}

1 个答案:

答案 0 :(得分:0)

因此,事实证明,由QRegularExpression实现的PCRE2库具有一个MATCH_LIMIT变量,其默认值为10,000,000(在该库的config.h文件中)。这与“惰性”匹配的性质结合在一起(在这种情况下,将搜索向前推进一个字符就算是与MATCH_LIMIT的匹配)解释了我所看到的。这很不幸,因为我认为在此示例中,惰性匹配的性能非常好。

PCRE2库允许覆盖MATCH_LIMIT变量以进行搜索,但是QRegularExpression中未实现此功能。我可以修补Qt库或更改PCRE2库的默认值并重新构建,但是到目前为止,我已经根据一篇不错的文章here找到了另一种(很难理解的)正则表达式:

^begin\n((?:[^\n]++|\n(?!end))*+)\nend