我有一堆 JSON 文件,用 Python 和 Ruby 处理,看起来像这样:
{
"KEY1": "foo",
"KEY2": "bar",
"URL": "https://{KEY2}.com/{KEY1}",
"IMPORTANT_THING": "repos/{KEY1}",
"NOTE": "This thing is {KEY1}{KEY2}ed",
"PYTHON_ONLY_THING": "{}/test/{}.py"
}
请注意,键的显示顺序不一致,我不想更改 JSON。
这是我的测试代码,显示了我到目前为止所做的尝试:
my_config = {"KEY1"=>"foo",
"KEY2"=>"bar",
"URL"=>"https://{KEY2}.com/{KEY1}",
"IMPORTANT_THING"=>"repos/{KEY1}",
"NOTE"=>"This thing is {KEY1}{KEY2}ed",
"PYTHON_ONLY_THING"=>"{}/test/{}.py"}
my_config.each_key do |key|
# Braindead, hard-coded solution that works:
# my_config[key].gsub!("{KEY1}", my_config["KEY1"])
# my_config[key].gsub!("{KEY2}", my_config["KEY2"])
# More flexible (if it would work):
# my_config[key].gsub!(/{.*}/, my_config['\0'.slice(1,-2)])
my_config[key].gsub!(/{.*}/) {|s| my_config[s.slice(1,-2)]}
end
puts my_config
我现在正在使用 braindead 解决方案,它会产生预期的输出:
{"KEY1"=>"foo", "KEY2"=>"bar", "URL"=>"https://bar.com/foo", "IMPORTANT_THING"=>"repos/foo", "NOTE"=>"This thing is foobared", "PYTHON_ONLY_THING"=>"{}/test/{}.py"}
但我想让它更加灵活和可维护。第一个“更好”的解决方案显然会引发错误,因为 slice 对 '\0' 本身而不是匹配项进行操作,而且我不确定它是否会匹配多次。当前未注释的解决方案不起作用,因为第二部分似乎一次对一个字母进行操作,而不是像我预期的那样对每个匹配项进行操作,因此它只是删除了花括号中的内容。更糟糕的是,它会删除 PYTHON_ONLY_THING 中外括号之间的所有内容,这并不好。
我认为我需要同时更改正则表达式和 Ruby 代码才能正常工作,但我不确定到哪里寻求更多帮助。或者 gsub 可能不是这项工作的正确工具。有什么想法吗?
我在 Linux x86_64 上使用 Ruby 2.3.7。
最佳答案
使用String#gsub
带有用于替换的初始哈希:
my_config.map do |k, v|
[
k,
v.gsub(/(?<={)[^}]+(?=})/, my_config).gsub(/{(?!})|(?<!{)}/, '')
]
end.to_h
#⇒ {"KEY1"=>"foo",
# "KEY2"=>"bar",
# "URL"=>"https://bar.com/foo",
# "IMPORTANT_THING"=>"repos/foo",
# "NOTE"=>"This thing is foobared",
# "PYTHON_ONLY_THING"=>"{}/test/{}.py"}
从 Ruby 2.4(或使用 Rails)开始,使用 Hash#transform_values
可能会更简单。
如果您不喜欢第二个 gsubbing,请提前转换哈希:
my_substs = my_config.map { |k, v| ["{#{k}}", v] }.to_h
my_config.map do |k, v|
[k, v.gsub(/{[^}]+}/, my_substs)]
end.to_h
关于ruby - 如何在 Ruby 中使用散列键进行这些字符串替换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50841540/