为什么这个Regexp使用pcre而不是Python的步数减少了99.89%?

我刚刚在
regex101编辑器中构建了这个表达式,但是偶然忘记将它转换为
Python flavor语法.我不熟悉差异,但认为它们相当小.他们不是.

Perl / pcre比Python步骤少了99.89%(6,377,715对6,565步)

https://regex101.com/r/PRwtJY/3

正则表达式:

^(\d{1,3}) +((?:[a-zA-Z0-9\(\)\-≠,]+ )+) +£ *((?:[\d]  {1,4}|\d)+)∑([ \d]+)?

任何帮助,将不胜感激!谢谢.

编辑

数据源是从PDF中提取的多行文本,导致输出不完美(可以看到base source PDF here)

我正在尝试提取特定行的框号,标题和任何存在(填写)的数字.如果您查看上面的链接,您可以看到完整的示例.例如:

下面是Regex101的屏幕截图,显示正面匹配.最顶部的行匹配显示框号(155),标题(交易利润)和数字(5561).
《为什么这个Regexp使用pcre而不是Python的步数减少了99.89%?》

限制:

>理想情况下,如您在PCRE compiler中看到的那样提取值 – 在匹配之前或之后很少或没有额外的空格 – 只是框号,标题和值.
>只有在填写了数字/值时才匹配(例如,在上面的例子中为5561,因此不匹配紧随其后的行 – 框160,但匹配框165).
>格式在表单下方更改,我有一个单独的正则表达式,所以忽略它.

最佳答案 建议:使用支持原子组和占有量词的较新的
regex module.与您的初始PCRE表达相比,这减少了大约50%的步骤(见
a demo on regex101.com):

^
(\d{1,3})\s++
((?>[^£\n]+))£\s++
([ \d]+)(?>[^∑\n]+)∑\s++
([ \d]+)

要实现这一目标,您可以:

import regex as re
rx = re.compile(r'''
    ^
    (\d{1,3})\s++
    ((?>[^£\n]+))£\s++
    ([ \d]+)(?>[^∑\n]+)∑\s++
    ([ \d]+)''', re.M | re.X)

matches = [[group.strip() for group in m.groups()] for m in rx.finditer(data)]
print(matches)

除了给出的除外:

[['145', 'Total turnover from trade', '5    2    0  0  0', '0  0'], ['155', 'Trading profits', '5  5  6  1', '0  0'], ['165', 'Net trading profits ≠ box 155 minus box 160', '5    5  6  1', '0  0'], ['235', 'P rofits before other deductions and reliefs ≠ net sum of', '5  5  6  1', '0  0'], ['300', 'Profits before qualifying donations and group relief ≠', '5  5    6  1', '0     0'], ['315', 'Profits chargeable to Corporation Tax ≠', '5  5    6  1', '0     0'], ['475', 'Net Corporation Tax liability ≠ box 440 minus box 470', '1  0  5  6', '5  9'], ['510', 'Tax chargeable ≠ total of boxes 475, 480, 500 and 505', '1  0  5  6', '5  9'], ['525', 'Self-assessment of tax payable ≠ box 510 minus box 515', '1  0  5  6', '5  9'], ['600', 'Tax outstanding ≠', '1  0  5  6', '5  9']]
点赞