Многострочный разделитель регулярных выражений Python
Имея эту многострочную переменную:
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')]
Спасибо!
1 ответ
Вы можете использовать положительный прогноз, чтобы убедиться, что вы лениво сопоставляете значение правильно:
(\w+)\s=\s(.+?)(?=$|\n[A-Z])
^^^^^^^^^^^^
Для использования с модификатором DOTALL, чтобы .
может соответствовать символу новой строки. (?=$|\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+, кроме новой строки
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))