如何使用jq获取找到的值的索引路径?
问题描述:
说我有这样的JSON:如何使用jq获取找到的值的索引路径?
{
"json": [
"a",
[
"b",
"c",
[
"d",
"foo",
1
],
[
[
42,
"foo"
]
]
]
]
}
而且我要的是含有foo
jq
指数路径的数组:使用jq
以及如何
[
".json[1][2][1]",
".json[1][3][0][1]"
]
我能做到这一点? 我试过recurse | .foo
首先得到比赛,但是我收到一个错误:Cannot index array with string "foo"
。
答
首先,我不确定获得一组jq
程序的目的是什么。虽然存在这样做的手段,但它们很少有必要; jq不提供任何种类的eval
命令。
jq有一个路径的概念,它是一个字符串和数字的数组,表示JSON中元素的位置;这相当于预期输出中的字符串。举例来说,".json[1][2][1]"
将被表示为["json", 1, 2, 1]
。标准库包含几个可以用这个概念运行的功能,如getpath
,setpath
,paths
和leaf_paths
。
我们因此可以得到在给定的JSON所有叶的路径和遍历它们,选择那些对其中它们在输入值JSON是“foo”的,并产生一个阵列了出来:
jq '[paths as $path | select(getpath($path) == "foo") | $path]'
这将返回,您给定的输入,输出如下:
[
["json", 1, 2, 1],
["json", 1, 3, 0, 1]
]
现在,虽然它不应该是必要的,而且是最有可能的,你正在接近任何问题,你都面临着在错误的道路标志,可以将这些数组转换为jq路径字符串
".\(map("[\(tojson)]") | join(""))"
完整的脚本将因此会:通过下面的脚本将每个路径寻求
jq '[paths as $path | select(getpath($path) == "foo") | $path | ".\(map("[\(tojson)]") | join(""))"]'
,其输出是:
[
".[\"json\"][1][2][1]",
".[\"json\"][1][3][0][1]"
]
答
圣地亚哥的优秀节目可以进一步调整以产生所需格式的输出:
def jqpath:
def t: test("^[A-Za-z_][A-Za-z0-9_]*$");
reduce .[] as $x
("";
if ($x|type) == "string"
then . + ($x | if t then ".\(.)" else ".[" + tojson + "]" end)
else . + "[\($x)]"
end);
[paths as $path | select(getpath($path) == "foo") | $path | jqpath]
jq -f wrangle.jq input.json
[
".json[1][2][1]",
".json[1][3][0][1]"
]
太棒了,谢谢! –
错误的方法来解决这个问题,这个答案有助于更好地理解jq是如何工作的。谢谢! :) – Kaos