Соответствие регулярному выражению очень медленное - PullRequest
1 голос
/ 02 апреля 2010

Я пытаюсь проанализировать PDF-файл, чтобы извлечь из него текст (пожалуйста, не предлагайте библиотекам делать это, так как это часть изучения формата).
Я уже обработал спуск, чтобы поместить это в алфавитно-цифровой формат. Теперь мне нужно извлечь текст из текстовых блоков.
Итак, мой текущий шаблон BT.*?\((.*?)\).*?ET (с установленным DOTMATCHALL), чтобы соответствовать чему-то вроде:

BT
   /F13 12 Tf
   288 720 Td
   (ABC) Tj
ET

Единственное, что мне нужно, это текст ABC в скобках.
Выше приведен только такой формат, чтобы было понятно. В дефлированном тексте это может быть все в одной строке, а может и не быть. Нет гарантии, что BT / ET будет в начале строки. Там могут быть пробелы и текст до / после заключенного в скобки раздела, может не быть. Однако в каждом блоке BT / ET будет только одна секция в скобках.

Вышеприведенный шаблон работает, но действительно медленный, я полагаю, это потому, что библиотека регулярных выражений не может соответствовать шаблону, который совпадает с текстом между BT и (ABC) много раз.
Регулярное выражение предварительно скомпилировано в попытке ускорить его, но оно кажется незначительным.

Как я могу ускорить это?

Ответы [ 6 ]

3 голосов
/ 02 апреля 2010

Сколько таких блоков может появиться в документе?

Часто медленное выполнение Regex является результатом катастрофического обратного отслеживания, как описано здесь: http://www.regular -expressions.info / catastrophic.html

Я не знаю, какую технологию регулярных выражений вы используете, но вы можете попробовать использовать косвенные утверждения, как описано здесь: http://www.regular -expressions.info / lookaround.html

Они позволяют вам сначала просто сопоставить то, что вы хотите, ABC в скобках, а затем проверить, что ему предшествует какое-то значение, а затем другое значение.

1 голос
/ 02 апреля 2010

Вы уверены, что регулярное выражение верно и вытаскивает ABC как матч? Что это за движок регулярных выражений? Использование моего отладчика регулярных выражений показывает, что:

"BT.*?((.*?)).*?ET" не извлекает ABC и фактически должен найти строку 'ET', а затем вернуться назад, чтобы найти все остальное.

"BT.*?\\((.*?)\\).*?ET" работает, как и ожидалось, за один проход слева направо.

0 голосов
/ 02 апреля 2010

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

r"(?s)\bBT\b[^(]*\(([^)]*)\).*?\bET\b"
0 голосов
/ 02 апреля 2010

вот один без регулярных выражений. простой анализ строки с использованием внутренних компонентов Python.

>>> xtract="""
... BT
...    /F13 12 Tf
...    288 720 Td
...    (ABC) Tj
... ET
...
... """
>>> for chunk in xtract.split("ET"):
...     if "BT" in chunk:
...         for brace in chunk.split(")"):
...             if "(" in brace:
...                  print brace[brace.find("(")+1:]
...
ABC
0 голосов
/ 02 апреля 2010

На самом деле недостаточно информации для определенного ответа - или, возможно, вы предполагаете, что мы знаем о PDF больше, чем вы. Всегда ли в этих BT...ET разделах заключены в скобки? Всегда ли один из них? BT или ET всегда в начале строки? Если это так, я бы предложил

(?m)^BT[^()]*\((.*?)\)[^()]*?^ET

Если бы я знал, как PDF представляет буквальные скобки, я мог бы, вероятно, придумать что-нибудь более эффективное.

РЕДАКТИРОВАТЬ: Согласно спецификации PDF, буквенные скобки должны быть экранированы с обратной косой чертой, и есть множество других последовательностей обратной косой черты. Итак, попробуйте это:

(?s)\bBT\b[^()]*\(((?:[^()\\]*(?:\\.[^()\\]*)*))\)

Эта часть - [^()\\]*(?:\\.[^()\\]*)* - соответствует блоку текста, который может содержать экранированные символы (включая парены), но не экранированные. Я знаю, это выглядит некрасиво, но это наиболее эффективный способ, поскольку Python не поддерживает атомарные группы или собственнические квантификаторы.

(?s) позволяет . соответствовать символам новой строки, а \bBT\b гарантирует, что BT не является частью более длинного "слова". Я достаточно уверен, что это все, что мне нужно, чтобы соответствовать всему фактическому текстовому содержимому, поэтому я не беспокоюсь о сопоставлении материала после заключительного слова.

0 голосов
/ 02 апреля 2010

Вы не можете просто проанализировать PDF с помощью регулярного выражения для извлечения текста. В большинстве случаев текст внутри сжатых двоичных двоичных объектов или закодирован. PDF-файл с таким текстом показан как исключение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...