QRegularExpression ленивое сопоставление не работает для очень больших строк - PullRequest
0 голосов
/ 25 октября 2018

Я использую QRegularExpression в Qt 5.10.1 для извлечения фрагментов текста из файлов, которые связаны верхним и нижним колонтитулами.Например, рассмотрим следующий текст:

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

Затем я использовал бы следующее регулярное выражение для захвата части текста:

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

Ничего необычного здесь.Проблема в том, что если текстовый раздел очень большой (более 100 тыс. Строк), регулярное выражение перестает создавать совпадение.Я пробовал поиск в другом текстовом редакторе (TextPad), и он отлично работает, поэтому я подозреваю, что это связано с некоторой константой MAX_SIZE в QRegularExpression или, скорее, с библиотекой 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 голосов
/ 26 октября 2018

Получается, что библиотека PCRE2, реализованная QRegularExpression, имеет переменную MATCH_LIMIT, которая по умолчанию равна 10 000 000 (в файле config.h библиотеки).Это в сочетании с природой «ленивого» сопоставления (когда продвижение поиска вперед на один символ считается совпадением с MATCH_LIMIT) объясняет то, что я видел.Это прискорбно, потому что я думал, что производительность ленивого сопоставления была очень хорошей в этом примере.

Библиотека PCRE2 позволяет переопределять переменную MATCH_LIMIT для поиска, но эта функция не реализована в QRegularExpression.Я мог бы исправить библиотеку Qt или изменить библиотеку PCRE2 по умолчанию и пересобрать, но сейчас я нашел альтернативное (и гораздо более сложное для понимания) регулярное выражение, основанное на хорошей статье здесь :

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