#python #regex #django #dictionary #django-views
#python #регулярное выражение #django #словарь #django-представления
Вопрос:
У меня есть строка с допустимым словарем python внутри
data = "Some string created {'Foo': u'1002803', 'Bar': 'value'} string continue etc."
Мне нужно извлечь этот dict. Я пробовал с регулярным выражением, но по какой-то причине re.search(r"{(.*?)}", data)
не сработало. Есть ли лучший способ извлечь этот dict?
Комментарии:
1. Откуда вы берете строку? Почему это так выглядит? Не могли бы вы получить его в более удобном формате?
2. @jonrsharpe почему это важно для вопроса, так как оно есть, поэтому вопрос совершенно ясен.
3. Подстройте словарь, а затем используйте
ast.literal_eval(substr)
, чтобы превратить его в словарь.4. Потому что у вас, вероятно, проблема с XY , поэтому отвечать на нее так, как указано, — пустая трата вашего и нашего времени.
5. Вам нужно, чтобы ваша группа включала фигурные
{}
скобки, поэтому ваши скобки()
должны быть вне фигурных скобок в вашем регулярном выражении.
Ответ №1:
Из предложения @AChampion.
>>> import re
>>> import ast
>>> x = ast.literal_eval(re.search('({. })', data).group(0))
>>> x
{'Bar': 'value', 'Foo': '1002803'}
итак, шаблон, который вы ищете, это re.search('({. })', data)
Предполагалось, что вы должны были извлечь фигурные скобки вместе со строкой, поэтому ast.literal_eval
можете преобразовать строку в словарь python. вам также не нужен r
префикс как {
или }
в группе захвата, ()
он будет соответствовать буквально.
Комментарии:
1. Обратите внимание, что, поскольку регулярное выражение является жадным, это все равно работает в случае, когда есть вложенный
dict
, например"Some string created {'Foo': u'1002803', 'Bar': 'value', 'Baz': {1:2, 3:4}} string continue etc."
. Однако он завершается неудачей, если в строке более одного отдельногоdict
. Например."Some string created {'Foo': u'1002803', 'Bar': 'value'} string continue etc. Another dict: {1:2, 3:4}"
Для обработки последнего случая необходим синтаксический анализатор (или, если{
или}
может появиться где-либо еще в inстрока).2. @jpmc26, делающий его нежадным (
re.findall(r'{. ?}', data)
), должен обрабатывать дополнительные вхождения{ }
. но это испортило бы вложенные словари, поскольку они будут рассматриваться как разные случаи, когда они на самом деле являются частью более крупной группы. так что да, синтаксический анализатор действительно необходим для одновременной обработки обоих случаев.3. кстати, как вы узнали, что я отредактировал этот ответ (я просто проходил мимо и исправил некоторые опечатки в моих старых ответах :))
4. Редактирование поднимает вопрос. Я случайно увидел это на первой странице. Даже не заметил дату, когда я прокомментировал. lol
5. @jpmc26: Не могли бы вы уточнить, используя «синтаксический анализатор»? Я застрял с такой строкой. Я был бы очень признателен за помощь. ` ‘имя: «data dict» идентификатор: 2 nv6: falsenstats {n хосты {n cnt1: 256 n cnt2: 0 n } n группы {n cnt1: 1 n cnt2: 0 n } n критический {n cnt1:1 n cnt2: 0 n } n main_hosts {n cnt1: 256 n cnt2: 0 n } n} n group_id: «None»‘ ` Как мне получить словарь списка словарей из этого?
stats {hosts: {cnt1: 250, cnt2: 0}, groups: {cnt: 1, cnt2: 0}, etc, etc}
Ответ №2:
Лучший способ анализа словаря без необходимости использования eval
:
import re
import json
data = "Some string created {'Foo': '1002803', 'Bar': 'value'} string continue"
dict_object = json.loads(re.search('({. })', data).group(0).replace("'", '"'))
** Если анализируемый словарь содержит строковые значения в Юникоде (ссылающиеся на строку примера вопроса):
dict_object = json.loads(re.search('({. })', data).group(0).replace("u'", '"').replace("'", '"'))
Комментарии:
1. @MatthewBarlowe это действительно работает, протестировано в Python 3.9.9. Кроме того, json.loads — более безопасное выполнение, чем eval, особенно если ваша строка может быть заполнена пользователями, которые потенциально могут добавить вредоносный код.
2. @MatthewBarlowe если анализируемый словарь содержит строковое значение в юникоде (ссылающееся на исходную строку примера), попробуйте: dict_object = json.loads(re.search(‘({. })’, данные).группа (0).заменить («u»», «»‘).заменить(«‘», ‘»‘))
3. @Boris нет, это не так
u
, строка из примера OP вызывает ошибку синтаксического анализа, и на нее следует ссылаться в ответе4. @renzob, на который следует ссылаться в ответе, поскольку строка OP содержит
u
5. Согласовано
json.loads
, это более безопасный и лучший процесс, но он должен быть способен обрабатывать ввод OP, вот и все. Комментарий удален и поддержан
Ответ №3:
Ваше решение работает!
In [1]: import re
In [2]: data = "Some string created {'Foo': u'1002803', 'Bar': 'value'} string continue etc."
In [3]: a = eval(re.search(r"{(.*?)}", data).group(0))
In [4]: a
Out[4]: {'Bar': 'value', 'Foo': u'1002803'}
Комментарии:
1. Ненужное использование
eval
. -1