正则表达式匹配很慢

时间:2010-04-01 20:08:59

标签: python regex pdf

我正在尝试解析PDF以从中提取文本(请不要建议任何库来执行此操作,因为这是学习格式的一部分。)
我已经处理了缩小它以使用字母数字格式。我现在需要从文本块中提取文本 所以,我当前的模式是BT.*?\((.*?)\).*?ET(设置了DOTMATCHALL),以匹配以下内容:

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

我想要的唯一一点就是方括号中的文字ABC 上面的格式只是为了清楚地看到。在缩小的文本中,它可能全部在一行中,也可能不是。没有保证BT / ET将在一条线的起点。在括号内部分之前/之后可能有空格和文字,可能没有。但是,每个BT / ET块只有一个括号内的部分。

上面的模式有效,但实际上很慢,我认为这是因为正则表达式库无法匹配BT和(ABC)之间的文本多次匹配的模式。
正则表达式是预编译的,试图加快速度,但似乎可以忽略不计。

我怎样才能加快速度?

6 个答案:

答案 0 :(得分:3)

文档中可能出现多少块?

正常缓慢的正则表达式执行是灾难性回溯的结果,如下所述:http://www.regular-expressions.info/catastrophic.html

我不知道您正在使用哪种正则表达式技术,但您可以尝试使用外观断言,如下所述: http://www.regular-expressions.info/lookaround.html

这些允许您首先匹配您想要的内容,ABC在括号内,然后验证它前面有一些值,后跟一些其他值。

答案 1 :(得分:1)

你确定正则表达式是否正确并将ABC拉出来作为匹配?这是什么语言的正则表达式引擎?使用我的正则表达式调试器显示:

"BT.*?((.*?)).*?ET"没有提取ABC,实际上必须找到字符串'ET'然后回溯以找到其他所有内容。

"BT.*?\\((.*?)\\).*?ET"按预期工作,从左到右单次传递。

答案 2 :(得分:0)

您不能只使用正则表达式解析PDF来提取文本。在大多数情况下,文本内部压缩二进制blob或编码。带有这样的文字的PDF是非常例外的。

答案 3 :(得分:0)

确切的答案还没有足够的信息 - 或许你假设我们比你更了解PDF。这些BT...ET部分中是否始终包含带括号的块?总是只有其中一个吗? BTET始终位于一行的开头吗?如果是这样,我会建议

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

如果我知道PDF如何代表字面括号,我可能会想出更高效的东西。

编辑:根据PDF规范,字面括号必须使用反斜杠进行转义,并且还有许多其他反斜杠转义序列。所以试试这个:

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

此部分 - [^()\\]*(?:\\.[^()\\]*)* - 匹配可能包含转义字符(包括parens)的文本块,但不包含未转义的parens。我知道它看起来很难看,但它是最有效的方式,因为Python不支持原子组或占有量词。

(?s)允许.匹配换行符,而\bBT\b可确保BT不属于较长的“单词”。我有理由相信这就是我需要匹配所有实际文本内容的所有内容,因此我不会在收尾后对这些内容进行匹配。

答案 4 :(得分:0)

这里没有正则表达式。使用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

答案 5 :(得分:0)

由于BTET之间只有一个括号内的表达式,因此您可以尝试使用以下正则表达式来提高速度:

r"(?s)\bBT\b[^(]*\(([^)]*)\).*?\bET\b"
相关问题