我有文本格式的数据,其中键/值对之间用分号分隔,后面可能跟空格,例如,可能不是“;”。或“;”,甚至“;”。线对之间始终会有分号,并且字符串以分号结尾。
键和值由空格分隔。
此字符串是扁平的。没有任何嵌套。字符串总是用引号引起来,而数值则不用引号引起来。我可以指望这在输入中保持一致。例如,
'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]]
要求使用[[奶酪],[斯蒂尔顿],[鸽子],17,[颜色],[蓝色],[为什么],[因为我这么说]]这样的列表。但是我不知道要使用这种形式的正则表达式。我最近的是
([^;[\s]*]+)
哪个返回
['', 'cheese', ' ', '"stilton"', ';', 'pigeons', ' ', '17', '; ', 'color', ' ', '"blue"', '; ', 'why', ' ', '"because', ' ', 'I', ' ', 'said', ' ', 'so"', ';']
当然,通过三位迭代并选择键/值对并忽略捕获的定界符很容易,但是我想知道是否存在不捕获定界符的正则表达式。有什么建议吗?
答案 0 :(得分:1)
在这里使用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'}
这当然假定您不在数据中的任何地方使用;
。
答案 1 :(得分:1)
您可以使用
r'(\w+)\s+("[^"]*"|[^\s;]+)'
使用re.findall
进行匹配和提取数据,并对第2组的值进行后处理以删除第一个和最后一个"
字符,如果第一个备用字符匹配,则创建一个字典条目。 / p>
请参见regex demo。
详细信息
(\w+)
-第1组(键):一个或多个单词字符\s+
-1个以上的空格字符("[^"]*"|[^\s;]+)
-第2组:"
,除"
以外的0多个字符,然后为"
或除空格和;
以外的1个或更多字符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)