1

有这个多行变量:

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')]

谢谢!

4

1 回答 1

1

您可以使用积极的前瞻来确保您正确地延迟匹配该值:

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

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

请参阅正则表达式演示

另一种更快的正则表达式(因为它是上述表达式的展开版本) - 但 DOTALL 修饰符不应与它一起使用:

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

查看另一个正则表达式演示

说明

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

Python演示

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))
于 2016-06-01T10:59:19.623 回答