Regex для анализа строки с разделителями с парами ключ / значение (python) - PullRequest
1 голос
/ 25 мая 2019

У меня есть данные в текстовом формате, где пары ключ / значение отделяются точкой с запятой, может следовать пробел, может быть, нет, например, ";"или ";", или даже ";".Между парами всегда будет точка с запятой, а строка заканчивается точкой с запятой.

Ключи и значения разделяются пробелом.

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

'cheese "stilton";pigeons 17; color "blue"; why "because I said so";'

В конечном итоге это выглядит как

{'cheese': "stilton", 'pigeons': 17, 'color': "blue"; 'why': "because I said so"}

Разные строки могут включать разные пары ключ / значение, и я заранее не знаю, какие ключи будут присутствовать,Так что это в равной степени допустимая входная строка:

mass 6.02 ; mammal "gerbil";telephone "+1 903 555-1212"; size "A1";

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

x = PATTERN.split(s)
d = {}
for i in range(0, len(x), 2):
    d[x[i]] = d[x[i+1]]

, для которого требуется список типа ['cheese', 'stilton', 'голуби', 17, 'color', 'blue', 'Why', 'потому что я так сказал'],Но я не могу найти регулярное выражение, чтобы войти в эту форму.Самое близкое, что у меня есть, это

([^;[\s]*]+)

, который возвращает

['', 'cheese', ' ', '"stilton"', ';', 'pigeons', ' ', '17', '; ', 'color', ' ', '"blue"', '; ', 'why', ' ', '"because', ' ', 'I', ' ', 'said', ' ', 'so"', ';']

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

Ответы [ 2 ]

1 голос
/ 25 мая 2019

Вы можете использовать

r'(\w+)\s+("[^"]*"|[^\s;]+)'

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

См. демонстрационную версию regex .

Подробности

  • (\w+) -Группа 1 (ключ): одно или несколько символов слова
  • \s+ - 1+ пробельных символов
  • ("[^"]*"|[^\s;]+) - Группа 2: ", 0+ символов, отличных от "а затем " или 1 или более символов, кроме пробелов и ;

Python demo :

import re
rx = r'(\w+)\s+("[^"]*"|[^\s;]+)'
s = 'cheese "stilton";pigeons 17; color "blue"; why "because I said so";'
result = {}
for key,val in re.findall(rx, s):
    if val.startswith('"') and val.endswith('"'):
        val = val[1:-1]
    result[key]=val

print(result)
1 голос
/ 25 мая 2019

Может быть проще использовать findall() вместо split() здесь. Это позволит вам использовать группу захвата, чтобы вытащить только ту часть, которую вы хотите. Затем вы можете разделить группы, очистить и т.д .:

import re
s = 'cheese "stilton";pigeons 17; color "blue"; why "because I said so";'
pairs = re.findall(r'(\S+?) (.+?);', s)

d = {}
for k, v in pairs:
    if  v.isdigit():
        v = int(v)
    else:
        v = v.strip('"')
    d[k] = v
print(d)

результат

{'cheese': 'stilton',
 'pigeons': 17,
 'color': 'blue',
 'why': 'because I said so'}

Это, конечно, предполагает, что вы не используете ; где-либо в данных.

...