Python 正则表达式匹配非常慢

Python 正则表达式匹配非常慢,python,regex,pdf,Python,Regex,Pdf,我正在尝试解析PDF以从中提取文本。请不要建议任何库这样做,因为这是学习格式的一部分。 我已经处理过将其压缩成字母数字格式。我现在需要从文本块中提取文本。 因此,我当前的模式是BT.*.*.*.*.*ET,其中DOTMATCHALL设置为匹配以下内容: BT /F13 12 Tf 288 720 Td (ABC) Tj ET 我想要的唯一一点是括号中的文本ABC。 上面的格式只是为了清楚地看到。在缩减的文本中,它可能全部在一行中,也可能不是。无法保证BT/ET将位于线路的起点

我正在尝试解析PDF以从中提取文本。请不要建议任何库这样做,因为这是学习格式的一部分。 我已经处理过将其压缩成字母数字格式。我现在需要从文本块中提取文本。 因此,我当前的模式是BT.*.*.*.*.*ET,其中DOTMATCHALL设置为匹配以下内容:

BT
   /F13 12 Tf
   288 720 Td
   (ABC) Tj
ET
我想要的唯一一点是括号中的文本ABC。 上面的格式只是为了清楚地看到。在缩减的文本中,它可能全部在一行中,也可能不是。无法保证BT/ET将位于线路的起点。括号内的部分前后可能有空格和文字,但可能没有。然而,每个BT/ET块只有一个带括号的部分

上面的模式可以工作,但速度非常慢,我认为这是因为regex库多次未能匹配BT和ABC之间文本的模式。 regex是为了加速而预先编译的,但它似乎可以忽略不计


我怎样才能加快速度

一个文档中可能会出现多少这样的块

正则表达式执行缓慢通常是灾难性回溯的结果,如下所述:

我不知道您使用的是什么regex技术,但您可以尝试使用lookaround断言,如下所述:


这些选项允许您首先匹配所需的内容,即括号内的ABC,然后验证其前面是否有某个值,后面是否有其他值。

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

BT.*?*?*?*?ET不会提取ABC,事实上必须找到字符串“ET”,然后回溯到其他所有内容


BT.\.\.\.\.*ET从左到右的单次传递可以正常工作。

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

没有足够的信息来给出明确的答案,或者你可能认为我们对PDF的了解比你多。这些BT…ET部分中是否总是有括号中的块?总是只有一个吗?BT或ET是否始终位于线路的开头?如果是的话,我建议

(?m)^BT[^()]*\((.*?)\)[^()]*?^ET
如果我知道PDF如何表示文字括号,我可能会想出更有效的方法

编辑:根据PDF规范,文字括号必须用反斜杠转义,还有一系列其他反斜杠转义序列。所以试试这个:

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


?s允许。以匹配换行符,并且\bBT\b确保BT不是较长单词的一部分。我有理由相信,这就是匹配所有实际文本内容所需的全部内容,因此我不必在结束排列后再去匹配这些内容。

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

由于BT和ET之间只有一个括号内的表达式,因此可以尝试以下正则表达式以提高速度:

r"(?s)\bBT\b[^(]*\(([^)]*)\).*?\bET\b"

我认为你的正则表达式格式不正确。你可以试着把它放在backticks`foo`中,看看显示是否正确。你用的是什么语言?正则表达式有许多变体。它是反勾选的。解析器是python的实现,引擎是python的。我正在使用一个在线工具进行测试,该工具报告它在正确的块中拉出。大量的块,所有的文本都在一个块中,但是你可能会在块中得到几个值得的段落。你没有看到我提到我已经缩小了块吗?问题中的文本摘录是实际的PDF格式。如果您不相信我的话,请看一下规范。是的,但是如果文本是WinANSI编码的,而不是子集,则对其进行压缩才有效。TJ命令中的值是索引值,只有当它是WinANSI编码的而不是子集时,索引值才与文本值相同。否则,它们需要使用嵌入式CMAP或PDF参考文件附录D中的表格进行转换。嘿,看看PDF规范。也许以后不要这么快就否决投票。我在我们的博客上对Tj命令做了更长更详细的解释,括号用ascii字符表示。它就像一个文本流,只有一些特殊的控制字符。我在问题中放了一些关于PDF的信息,就在我要找的示例部分的下面。Gskinner的在线测试人员对此很满意,但是python报告了一个“raiseerror,v invalid expression”“sre_constants.error@unexpected end of regular expression”,但它看起来像
所有括号/括号都是匹配的。在这个python正则表达式测试仪中它对我有效:\bBT\b[^%28%29]*\%28%28%3F%3A[^%28%29\]*%28%3F%3A\\\.[^%28%29\]*%29*%29*%29最终,这是这里唯一一个速度合理的答案。有趣的是,这似乎只找到第二个块BT/ET块中的一个;如果使用.finditer,将获得所有匹配项。除非我误解了你的评论。