Python 多行正则表达式分隔符

Python multiline regex delimiter

有这个多行变量:

raw = '''
CONTENT = ALL
TABLES = TEST.RAW_1
        , TEST.RAW_2
        , TEST.RAW_3
        , TEST.RAW_4
PARALLEL = 4
'''

结构总是 TAG = CONTENT,两个字符串都不是固定的,CONTENT 可以包含新行。

我需要一个regex来获得:

[('CONTENT', 'ALL'), ('TABLES', 'TEST.RAW_1\n        , TEST.RAW_2\n        , TEST.RAW_3\n        , TEST.RAW_4\n'), ('PARALLEL', '4')]

尝试了多种组合,但我无法 停止 regex 引擎 TABLES 标签,因为它的内容是由下一个标签分隔的 多行字符串

一些尝试来自口译员:

>>> re.findall(r'(\w+?)\s=\s(.+?)', raw, re.DOTALL)
[('CONTENT', 'A'), ('TABLES', 'T'), ('PARALLEL', '4')]


>>> re.findall(r'^(\w+)\s=\s(.+)?', raw, re.M)
[('CONTENT', 'ALL'), ('TABLES', 'TEST.RAW_1'), ('PARALLEL', '4')]


>>> re.findall(r'(\w+)\s=\s(.+)?', raw, re.DOTALL)
[('CONTENT', 'ALL\nTABLES = TEST.RAW_1\n        , TEST.RAW_2\n        , TEST.RAW_3\n        , TEST.RAW_4\nPARALLEL = 4\n')]

谢谢!

您可以使用积极的前瞻来确保您懒惰地正确匹配值:

(\w+)\s=\s(.+?)(?=$|\n[A-Z])
                ^^^^^^^^^^^^

与 DOTALL 修饰符一起使用,以便 . 可以匹配换行符。 (?=$|\n[A-Z]) 前瞻将要求 .+? 匹配到字符串的末尾,或者匹配到后跟大写字母的换行符。

参见regex demo

还有替代方案,更快的正则表达式(因为它是上述表达式的展开版本)- 但 DOTALL 修饰符不应与它一起使用:

(\w+)\s*=\s*(.*(?:\n(?![A-Z]).*)*)

another regex demo

解释:

  • (\w+) - 第 1 组捕获 1+ 个单词字符
  • \s*=\s* - = 符号用可选的 (0+) 空格包裹
  • (.*(?:\n(?![A-Z]).*)*) - 第 2 组捕获 0+ 个序列:
    • .* - 除换行符外的任何 0+ 个字符
    • (?:\n(?![A-Z]).*)* - 0+ 个序列:
      • \n(?![A-Z]) - 换行符后面没有大写 ASCII 字母
      • .* - 除换行符外的任何 0+ 个字符

Python demo:

import re
p = re.compile(r'(\w+)\s=\s(.+?)(?=$|\n[A-Z])', re.DOTALL)
raw = '''
CONTENT = ALL
TABLES = TEST.RAW_1
        , TEST.RAW_2
        , TEST.RAW_3
        , TEST.RAW_4
PARALLEL = 4
'''
print(p.findall(raw))