我使用以下字符串:
'"name": "Gnosis", \n "symbol": "GNO", \n "rank": "99", \n "price_usd": "175.029", \n "price_btc": "0.0186887", \n "24h_volume_usd": "753877.0"'
我必须在python中使用re.sub()
来仅替换包含数字的双引号("
),以便稍后在JSON中解析它。我试过一些正则表达式,但没有成功。这是我最好的尝试:
exp = re.compile(r': (")\D+\.*\D*(")', re.MULTILINE)
response = re.sub(exp, "", string)
我经常搜索类似的问题,但没有找到另一个类似的问题。
最后我使用了(感谢S. Kablar):
fomatted = re.sub(r'"(-*\d+(?:\.\d+)?)"', r"\1", string)
parsed = json.loads(formatted)
问题是this endpoint将格式错误的字符串作为JSON返回。
其他用户answered"首先用json解析字符串,然后将数字转换为float"使用for循环,我认为,这是一种非常有效的方法,你也将被迫在你的响应中选择int或float类型。为了避免疑问,我写了this gist,在那里我向您展示了不同方法与基准测试之间的比较,现在我在这种情况下会信赖正则表达式。
感谢大家的帮助
答案 0 :(得分:2)
首先用json解析字符串,然后将数字转换为浮点数:
string = '{"name": "Gnosis", \n "symbol": "GNO", \n "rank": "99", \n "price_usd": "175.029", \n "price_btc": "0.0186887", \n "24h_volume_usd": "753877.0"}'
data = json.loads(string)
response = {}
for key, value in data.items():
try:
value = int(value) if value.strip().isdigit() else float(value)
except ValueError:
pass
response[key] = value
答案 1 :(得分:1)
正则表达式:"(-?\d+(?:[\.,]\d+)?)"
替换:\1
详细说明:
()
捕获小组(?:)
非捕获组\d
匹配一个数字(等于[0-9]
)+
匹配一次且无限次?
匹配0到1次\1
第1组。Python代码:
def remove_quotes(text):
return re.sub(r"\"(-?\d+(?:[\.,]\d+)?)\"", r'\1', text)
remove_quotes('"percent_change_7d": "-23.43"') >> "percent_change_7d": -23.43
答案 2 :(得分:1)
你走近了。你想保存数字和冒号,所以你需要把它们放在括号中,而不是其余的。此外,数字为\d
,而不是\D
(不是 - 数字)。
所以:
exp = re.compile(r'(: *)"(\d+\.?\d*)"', re.MULTILINE)
response = re.sub(exp, "\\1\\2", string)
\d+\.?\d* means "a number (or more), a point (or not), any numbers"
上述内容不包括“.125”,即否数字,一个点。
如果你改为“\ d *。?\ d *”,那就匹配“。”,因为它是**任何数字“,一点,任何数字”。
我认为唯一可行的方法是
(\d+\.?\d*|\.\d+)
与|意思是“或”:所以,一个数字可选地后跟一个点和任何数字(这匹配“17.”),或一个点后跟至少一个数字。不幸的是,“\ d +。?\ d +”与“5”不匹配。
或者您指定所有三种情况:
(\d+|\d+\.?\d+|\.\d+)
第一个整数(\ d +),然后是带或不带小数的浮点数,然后是单独的小数部分,不带前导零。