从字符串中提取Python字典

9

我有一个包含有效Python字典的字符串

data = "Some string created {'Foo': u'1002803', 'Bar': 'value'} string continue etc."

我需要提取那个字典。我尝试使用正则表达式,但是由于某种原因 re.search(r"\{(.*?)\}", data) 没有起作用。有没有更好的方法来提取这个字典?


1
你从哪里获取这个字符串的?为什么它看起来是那样的?你能以更有用的格式获取它吗? - jonrsharpe
1
@jonrsharpe 这对问题的重要性是什么?它就是这样,所以问题非常清晰。 - Goran
2
因为你可能存在一个 XY 问题,所以如实回答这个问题可能浪费你和我们的时间。 - jonrsharpe
@Goran,你的问题很清楚,我们都明白你想要做什么。但是你到目前为止尝试过什么?你能展示一下你的代码来帮助指出错误出现的地方吗? - idjaw
1
你需要让你的组包含大括号 "{}",所以你的圆括号 "()" 需要在正则表达式的大括号之外。 - AChampion
显示剩余3条评论
3个回答

13

根据 @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前缀。


请注意,由于正则表达式是贪婪的,在存在嵌套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}"。需要使用解析器来处理后一种情况(或者如果在字符串中其他地方可能出现{})。 - jpmc26
@jpmc26 通过将其变为非贪婪模式(re.findall(r'{.+?}', data))可以处理额外的 {} 出现。但是,这样会使嵌套字典出现问题,因为它们被视为不同的出现,而实际上它们是大型组的一部分。因此,实际上需要解析器来同时处理这两种情况。 - danidee
顺便问一下,你是怎么知道我编辑了这个答案的(我只是路过并纠正了一些旧回答的拼写错误 :) ) - danidee
编辑会使问题重新浮现。我碰巧在首页看到了它。评论时甚至没有注意日期。哈哈 - jpmc26
@jpmc26:您能详细说明一下“使用解析器”的意思吗?我被这样的字符串卡住了。非常感谢您的帮助。'name: "data dict" id: 2\nv6: false\nstats {\n hosts {\n cnt1: 256\n cnt2: 0\n }\n groups {\n cnt1: 1\n cnt2: 0\n }\n critical {\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}, 等等,等等} - PixelatedPixie
@PixelatedPixie 请搜索一个与你的语法类似的问题,如果找不到,请发布一个新的问题。 - jpmc26

5
不使用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("'", '"'))

如果要解析的字典包含Unicode字符串值(参考问题中的示例字符串):

dict_object = json.loads(re.search('({.+})', data).group(0).replace("u'", '"').replace("'", '"'))

1
@MatthewBarlowe,这是有效的,已在Python 3.9.9中测试过。 此外,json.loads比eval更安全,特别是如果您的字符串可以由用户填写,他们可能会添加恶意代码。 - Boris
如果要解析的字典包含Unicode字符串值(引用原始示例字符串),请尝试以下操作: dict_object = json.loads(re.search('({.+})', data).group(0).replace("u'", '"').replace("'", '"')) - renzob
@Boris,不是这样的。OP示例中字符串中的u会导致解析错误,应在答案中提到它。 - Matthew Barlowe
@renzob 应该在回答中提到,因为 OP 的字符串包含一个 u - Matthew Barlowe
1
同意json.loads是更安全和更好的处理方式,但应该能够处理OP的输入。评论已删除并点赞。 - Matthew Barlowe

0

你的解决方案可行!

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 - jpmc26

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接