2016-09-23 5 views
0

У меня есть строка, которая выглядит как:питон: регулярное выражение - поймать переменное число групп

TABLE_ENTRY.0[hex_number]= <FIELD_1=hex_number, FIELD_2=hex_number..FIELD_X=hex> 
TABLE_ENTRY.1[hex_number]= <FIELD_1=hex_number, FIELD_2=hex_number..FIELD_Y=hex> 

количество полей неизвестно и варьируется от входа к входу, я хочу, чтобы захватить каждую запись отдельно со всеми его полей и их значений.

я придумал:

([A-Z_0-9\.]+\[0x[0-9]+\]=)(0x[0-9]+|0):\s+<(([A-Z_0-9]+)=(0x[0-9]+|0)) 

, которая соответствует записи в таблице и первое поле, но я не знаю, как объяснить переменное количество полей.

для ввода:

ENTRY_0[0x130]=0: <FIELD_0=0, FIELD_1=0x140... FIELD_2=0xff3> 

вывод должен быть:

ENTRY 0: 
     FIELD_0=0 
     FIELD_1=0x140 
     FIELD_2=ff3 
ENTRY 1: 
     ... 
+1

Каков конечный результат, который вы ищете? –

+0

Приведите пример в вопрос – susdu

+0

Можете ли вы привести конкретный пример? Текст в вашем вопросе кажется своего рода описанием синтаксиса, а не примером, верно? – phynfo

ответ

3

Короче говоря, все это невозможно сделать в двигателе re. Вы не можете генерировать больше групп динамически. Все это будет помещено в одну группу. Вы должны повторно проанализировать результаты так:

import re 
input_str = ("TABLE_ENTRY.0[0x1234]= <FIELD_1=0x1234, FIELD_2=0x1234, FIELD_3=0x1234>\n" 
      "TABLE_ENTRY.1[0x1235]= <FIELD_1=0x1235, FIELD_2=0x1235, FIELD_3=0x1235>") 
results = {} 
for match in re.finditer(r"([A-Z_0-9\.]+\[0x[0-9A-F]+\])=\s+<([^>]*)>", input_str): 
    fields = match.group(2).split(", ") 
    results[match.group(1)] = dict(f.split("=") for f in fields) 

>>> results 
{'TABLE_ENTRY.0[0x1234]': {'FIELD_2': '0x1234', 'FIELD_1': '0x1234', 'FIELD_3': '0x1234'}, 'TABLE_ENTRY.1[0x1235]': {'FIELD_2': '0x1235', 'FIELD_1': '0x1235', 'FIELD_3': '0x1235'}} 

Выход только будет большой ДИКТ состоящий из записи таблицы, в Словаре из его полей.

Это также весьма удобно, как вы можете сделать это:

Я лично предлагаю вырезают «TABLE_ENTRY», как это repetative, но, как вы хотите.

+0

каждый день я заново открываю, как легкий питон, спасибо. – susdu

+0

Если я удаляю новую строку из строки ввода, она больше не отображает 2 совпадения, почему? Я получаю: ('TABLE_ENTRY.0', '0x3242', 'FIELD_1 = 0x1234, FIELD_2 = 0x1234, FIELD_3 = 0x1234> TABLE_ENTRY.1 [0x1235] = 0x98789: susdu

+0

должно быть \ s + <([^>] *)> вместо \ s + <(.*)> – susdu

1

Используйте захват группы для соответствия непригодных длины:

([A-Z_0-9\.]+\[0x[0-9]+\]=)\s+<(([A-Z_0-9]+)=(0x[0-9]+|0),\s?)*([A-Z_0-9]+)=(0x[0-9]+|0) 

Следующая часть соответствует каждый ряд полей с запятая и пробелы

(([A-Z_0-9]+)=(0x[0-9]+|0),\s?)* 

И ([A-Z_0-9]+)=(0x[0-9]+|0) будет соответствовать последнему полю.

Демо: https://regex101.com/r/gP3oO6/1

Примечание: Если вы не хотите, чтобы некоторые группы лучше использовать не захватывая группы путем добавления ?: в ведущих групп захвата ((?: ...)), и обратите внимание, что (0x[0-9]+|0):\s+ в качестве дополнительных в. ваше регулярное выражение (на основе вашего шаблона ввода)

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