Как разделить только некоторые символы в строке

#python #regex

Вопрос:

Мне нужно преобразовать строку SQL в словарь. Учитывая следующую частичную строку:

 'field_1="value_1", field_2=1234'
 

Я хочу создать следующий словарь:

 {"field_1": "value_1", "field_2": 1234}
 

С помощью:

 text = text.replace(",", "=")
text = text.split("=")
text = [i.strip() for i in text]
col_names = text[::2]
values = text[1::2]
dict_ = dict(zip(col_names, values))
 

Я подхожу так близко, как:

 {'field_1': '"value_1"', 'field_2': '1234'}
 

Я почти уверен, что смогу разобраться с дополнительными кавычками, однако я борюсь с этой строкой, потому что запятая внутри кавычек разрушает мою split() :

 'field_1="value_1a, value_1b", field_2=1234'
 

У меня такое чувство, что я мог бы использовать здесь регулярное выражение для решения проблем с кавычками и дополнительными запятыми, но я не могу определить точный синтаксис. Значения иногда могут быть строками, а иногда целыми числами/числами с плавающей точкой. Имена полей могут значительно различаться, и после запятых не всегда есть пробелы. В конце строки также нет запятой.

Заранее спасибо!

Комментарии:

1. Вам нужно написать более сложный синтаксический анализатор, который проверяет такие вещи, как " указание строки.

2. Вам нужно сначала разделиться на запятые , и только потом разбираться с кавычками " .

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

4. Откуда вы получаете запрос? Не могли бы вы опубликовать все это (чтобы иметь более широкий контекст)? Некоторые системы БД способны использовать формат JSON .

5. @CristiFati — SQL поступает из API через модуль запросов. Вот более длинный образец: 'uta (rating_t=55 where id_t=16936\r\nuta (entry_t=55 where id_t=16936\r\nuta (race_t=55 where id_t=16936\r\nuta (rating_t=55 where id_t=17286\r\nuta (entry_t=55 where id_t=17286\r\nuta (race_t=55 where id_t=17286\r\nuta (singles_t=7254 where id_t=16936\r\nuta (doubles_t=7255 where id_t=16936\r\nuta (prize_t="$541K" where id_t=17286\r

Ответ №1:

Вот очень простой подход, который сделает эту работу за вас:

 def parse(s):
    buf = []
    token = ""
    quotes = False
    punct = {",", "="}
    for c in s:
        if c == '"':
            quotes = not quotes
        elif c in punct and not quotes:
            buf.append(token)
            token = ""
        elif c != " " or quotes:
            token  = c
    buf.append(token)
    return dict(zip(buf[::2], buf[1::2]))

print(parse('field_1="value_1a, value_1b", field_2=1234'))
# {'field_1': 'value_1a, value_1b', 'field_2': '1234'}
 

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

Я надеюсь, что это даст вам правильное направление.

Ответ №2:

Как сказал Гжегож Оледзки, вы захотите разделить свои запятые, а затем «разобраться» (удалить) свои цитаты после этого

 x = 'field_1="value_1", field_2=1234'

x = {i.split("=")[0]:i.split("=")[1].strip(""") for i in x.split(",")}
 
 {'field_1': 'value_1', ' field_2': '1234'}
 

Обратите внимание, что это не вычисляет целые числа, поэтому мы можем расширить это, чтобы выполнить это:

 import ast

x = 'field_1="value_1", field_2=1234'

x = {i.split("=")[0]:i.split("=")[1].strip(""") if i.split("=")[1].count(""") else ast.literal_eval(i.split("=")[1].strip(""")) for i in x.split(",")}
 
 {'field_1': 'value_1', ' field_2': 1234}
 

Комментарии:

1. Это не касается более сложного случая, представленного: 'field_1="value_1a, value_1b", field_2=1234'