考虑以下数组:
{
"A": 100,
"B": 200,
"C": "ccc",
"arr": [
{
"result": ".R1.R3",
"fmt": "%s::%s::baz",
"vals": [".A", ".B"]
},
{
"result": ".R2.R4",
"fmt": "%s/%s",
"vals": [".A", ".C"]
}
]
}
我需要用值替换某些格式的键来自其他密钥在某个数组的字符串中。
期望输出:
{
"A": 100,
"B": 200,
"C": "ccc",
"R1": {"R3": "100::200::baz"},
"R2": {"R4": "100/ccc"}
}
您没有指定要在.vals
数组项中引用到文档中的语言。如果您试图从那里执行(任意(jq
代码,请知道jq
无法使用作为字符串值提供的代码来执行。jq
也不提供使用%s
(和其他(的printf
风格的替换。因此,您要么需要重新实现一整套(第三方(功能,要么恢复到描述引用和替换的更简单的方案。
为了简单起见,此解决方案只是从.vals
数组项中删除第一个字符(点(,并将结果视为顶级字段名,然后简单地用下一个值替换每次出现的文字%s
。这应该会让您对一般技术有一个概述。
. as $top | reduce .arr[] as $a (del(.arr); .[$a.result] = (
reduce $a.vals[][1:] as $val ($a.fmt; sub("%s"; $top[$val] | @text))
))
{
"A": 100,
"B": 200,
"C": "ccc",
".R1": "100::200::baz",
".R2": "100/ccc"
}
演示
改进参考语言的一个非常简单的方法是使用jq
提供的函数的路径表达式。它们表示为数组,字段名表示为字符串项,数组索引表示为数字项。.A
变成["A"]
,.A[3].B
变成["A",3,"B"]
,依此类推
{
"A": 100,
"B": 200,
"C": "ccc",
"arr": [
{
"result": ".R1",
"fmt": "%s::%s::baz",
"vals": [["A"], ["B"]]
},
{
"result": ".R2",
"fmt": "%s/%s",
"vals": [["A"], ["C"]]
}
]
}
然后您可以使用getpath
来评估上面给出的路径表达式:
. as $top | reduce .arr[] as $a (del(.arr); .[$a.result] = (
reduce $a.vals[] as $path ($a.fmt; sub("%s"; $top | getpath($path) | @text))
))
{
"A": 100,
"B": 200,
"C": "ccc",
".R1": "100::200::baz",
".R2": "100/ccc"
}
演示
编辑:由于问题已被修改,.result
值现在也受到参考解释的约束,因此对.vals
采取的措施也适用于它。这意味着将建议的源文档格式更改为使用"result": ["R1", "R3"]
中的路径表达式,并将建议代码中的赋值从.[$a.result] = ...
更改为setpath($a.result; ...)
:
{
"A": 100,
"B": 200,
"C": "ccc",
"arr": [
{
"result": ["R1", "R3"],
"fmt": "%s::%s::baz",
"vals": [["A"], ["B"]]
},
{
"result": ["R2", "R4"],
"fmt": "%s/%s",
"vals": [["A"], ["C"]]
}
]
}
. as $top | reduce .arr[] as $a (del(.arr); setpath($a.result;
reduce $a.vals[] as $path ($a.fmt; sub("%s"; $top | getpath($path) | @text))
))
{
"A": 100,
"B": 200,
"C": "ccc",
"R1": {
"R3": "100::200::baz"
},
"R2": {
"R4": "100/ccc"
}
}
演示