jq:如何用值替换键​来自其他密钥​在某个数组的字符串中



考虑以下数组:

{
"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"
}
}

演示

最新更新