说我有这样的JSON:
{
"json": [
"a",
[
"b",
"c",
[
"d",
"foo",
1
],
[
[
42,
"foo"
]
]
]
]
}
我想要一个包含jq
的{{1}}索引路径数组:
foo
我可以使用[
".json[1][2][1]",
".json[1][3][0][1]"
]
实现此目标吗?
我尝试jq
先获得匹配,但收到错误:recurse | .foo
。
答案 0 :(得分:8)
首先,我不确定获得一系列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]"
]
答案 1 :(得分:2)
圣地亚哥优秀的程序可以进一步调整,以产生所需格式的输出:
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]"
]