2016-06-01 12 views
1

Имея этот многострочные переменный: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]) потребуется .+? для соответствия до конца строки или до новой строки, за которой следует буква в верхнем регистре.

См. 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)) 
+1

Удивительные объяснения! Огромное 'regex' * kung-fu * .. Большое спасибо Wiktor! – klashxx

 Смежные вопросы

  • Нет связанных вопросов^_^