Python 正则表达式中可变宽度回顾的替代方案

Alternatives to variable-width lookbehind in Python regex

我最近决定跳入 Python 池的深处并开始将我的一些 R 代码转换为 Python 我被困在一些非常重要的事情上大部头书。在我的工作中,我花了很多时间来解析文本数据,众所周知,这些数据是非常非结构化的。因此,我开始依赖正则表达式的环视功能,而 R 的环视功能非常强大。例如,如果我正在解析一个 PDF,当我对文件进行 OCR 时,它可能会在字母之间引入一些空格,那么我将通过这样的方式获得我想要的值:

oAcctNum <- str_extract(textBlock[indexVal], "(?<=ORIG\s?:\s?/\s?)[A-Z0-9]+")

在 Python 中,这是不可能的,因为 ? 的使用使 lookbehind 成为可变宽度的表达式,而不是固定宽度。这个功能对我来说非常重要,它阻止了我想要使用 Python,但我不想放弃这种语言,而是想知道 Pythonista 解决这个问题的方法。在提取文本之前是否必须预处理字符串?像这样:

oAcctNum = re.sub(r"(?<=\b\w)\s(?=\w\b)", "")
oAcctNum = re.search(r"(?<=ORIG:/)([A-Z0-9])", textBlock[indexVal]).group(1)

有没有更有效的方法来做到这一点?因为虽然这个例子很简单,但这个问题会以非常复杂的方式出现在我处理的数据中,我不想对我分析的每一行文本都进行这种预处理。

最后,如果这里不是问这个问题的合适地方,我深表歉意;我不确定还有什么地方可以 post 它。提前致谢。

在您描述的这种情况下,您需要使用 capture groups

"(?<=ORIG\s?:\s?/\s?)[A-Z0-9]+"

会变成

r"ORIG\s?:\s?/\s?([A-Z0-9]+)"

该值将在 .group(1) 中。请注意,首选原始字符串。

这是一个示例代码:

import re
p = re.compile(r'ORIG\s?:\s?/\s?([A-Z0-9]+)', re.IGNORECASE)
test_str = "ORIG:/texthere"
print re.search(p, test_str).group(1)

IDEONE demo

除非您需要重叠匹配,否则捕获组使用情况而不是回顾是相当简单的。

请注意,如果可以使用组,则通常不需要回顾。那么

怎么样
match = re.search(r"ORIG\s?:\s?/\s?([A-Z0-9]+)", string)
if match:
    text = match.group(1)

实践中:

>>> string = 'ORIG : / AB123'
>>> match = re.search(r"ORIG\s?:\s?/\s?([A-Z0-9]+)", string)
>>> match
<_sre.SRE_Match object; span=(0, 12), match='ORIG : / AB123'>
>>> match.group(1)
'AB123'
print re.findall(r"ORIG\s?:\s?/\s?([A-Z0-9]+)",test_str)

您可以直接使用 findall 这将 return 正则表达式中的所有组(如果存在)。