在主机上,我有一个环境变量,其值中包含引号,如:
export VALUE_WITH_QUOTE_FROM_OS='quote"value'
当我回应bash时,它很好
#echo $VALUE_WITH_QUOTE_FROM_OS
quote"value
我有一个以下的json字符串:
json_str = '{"key":"${VALUE_WITH_QUOTE_FROM_OS}"}'
然后我想在进一步处理之前在python脚本中扩展环境变量,类似这样
json_str = os.path.expandvars(json_str)
json_dict = json.loads(json_str)
但是,这种扩展会破坏json语法,因为json_str已经变成
'{"key":"quote"value"}' (<== bad unescaped quote in the value)
而不是
'{"key":"quote\"value"}'
无论如何我可以在扩展值时通知os.path.expandvars()以逃避双引号?如果没有,我应该如何扩展环境变量,以便可以转义双引号。
注1 环境变量的值是一个安全令牌,因此我必须保持双引号不变。
注意2 当前的json接口已经确定并且可以按原样使用。这个json_str传递给我,因此我应该而且必须只扩展json字符串中$ {}表示的环境变量,不允许进行其他修改。
注3 此json_str非常大,具有复杂,动态,嵌套的结构,并且由无法访问主机os环境变量的多个客户端使用。虽然我可以首先加载json_str,遍历字典来解析环境变量,然后将dict转发回json_str,然后发送给所有客户端,我认为与处理它相比效率较低就像一个字符串。
感谢。
答案 0 :(得分:2)
我当然不保证这会带来os.path
的可移植性,但这应该主要适用于我认为使用posix的系统:
import re
import os
import json
regex = re.compile(r'\$(\w+|\{[^}]*\})')
json_str = '{"key":"${FOO}"}'
def os_expandvar(match):
v = match.group(1)
if v.startswith('{') and v.endswith('}'):
v = v[1:-1]
return json.dumps(os.environ.get(v, ''))[1:-1]
print(regex.sub(os_expandvar, json_str))
正则表达式(以及一般的实现思路)借鉴了posixpath
模块中os.path.expandvars
的实现。我删除了很多复杂性来简化答案,但如果你发现需要它,你可以把它重新放回去。
这应该处理替换字符串为$FOO
或${FOO}
的情况,这在posix系统中是典型的。
此处还有其他选项...根据您提供的示例,您可以先解码json ,然后展开所有值。根据json的格式,您可能需要一个递归函数来完成工作:
# untested
def json_expandvars(o):
if isinstance(o, dict):
return {json_expandvars(k): json_expandvars(v) for k, v in o.items()}
elif isinstance(o, list):
return [json_expandvars(v) for v in o]
elif isinstance(o, basestring):
return os.path.expandvars(o)
else:
return o
json_dict = json_expandvars(json.loads(json_str))
答案 1 :(得分:0)
os.path.expandvars
无法知道结果必须是有效的JSON字符串,并且引号已转义。
相反,在将JSON解码为字典后,将环境变量扩展为。
json_dict = json.loads(json_str);
json_dict['key'] = os.path.expandvars(json_dict['key']);