【问题标题】:Alternatives to variable-width lookbehind in Python regexPython 正则表达式中可变宽度lookbehind的替代方案
【发布时间】:2015-10-12 09:23:22
【问题描述】:

我最近决定跳入 Python 池的深处,开始将我的一些 R 代码转换为 Python,但我被困在对我来说非常重要的事情上。在我的工作中,我花费大量时间解析文本数据,众所周知,文本数据非常非结构化。结果,我开始依赖正则表达式的环视功能,而 R 的环视功能非常强大。例如,如果我解析的 PDF 可能会在 OCR 文件时在字母之间引入一些空格,我会通过以下方式获得我想要的值:

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

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

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

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

最后,如果这里不适合提出这个问题,我深表歉意;我不确定在哪里发布它。提前致谢。

【问题讨论】:

  • regex 模块支持可变宽度的lookbehinds。另见stackoverflow.com/q/11640447/3001761
  • @jonrsharpe 谢谢你,很高兴知道!不过,看看下面的答案,我开始怀疑我对环视的依赖。但是,再次感谢您将我指向 regex 模块。

标签: python regex lookaround


【解决方案1】:

在您描述的这种情况下,您需要使用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

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

【讨论】:

  • 你提出了一个非常好的观点。看起来是时候开始重新考虑我的正则表达式方法了。
  • 重点是:如果您不需要重叠匹配,请使用捕获组方法。 Look-behinds 是资源消耗,只是在性能方面是昂贵的。有时,没有什么大的区别,但如果后视时间很长,那么区别可能是显而易见的。
【解决方案2】:

请注意,如果您可以使用组,则通常不需要lookbehinds。那么怎么样

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'

【讨论】:

  • 感谢Antii的回复!您和 stribizhev 有相同的想法,这似乎是最好的做法。是时候重写一些代码了...
【解决方案3】:
print re.findall(r"ORIG\s?:\s?/\s?([A-Z0-9]+)",test_str)

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

【讨论】:

    猜你喜欢
    • 2012-07-23
    • 1970-01-01
    • 2014-11-04
    • 1970-01-01
    • 1970-01-01
    • 2017-06-14
    • 2018-03-22
    • 2017-08-17
    相关资源
    最近更新 更多