如何使用jq获取找到的值的索引路径?

问题描述:

说我有这样的JSON:如何使用jq获取找到的值的索引路径?

{ 
    "json": [ 
    "a", 
    [ 
     "b", 
     "c", 
     [ 
     "d", 
     "foo", 
     1 
     ], 
     [ 
     [ 
      42, 
      "foo" 
     ] 
     ] 
    ] 
    ] 
} 

而且我要的是含有foojq指数路径的数组:使用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,pathsleaf_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]" 
] 
+0

太棒了,谢谢! –

+1

错误的方法来解决这个问题,这个答案有助于更好地理解jq是如何工作的。谢谢! :) – Kaos

圣地亚哥的优秀节目可以进一步调整以产生所需格式的输出:

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]" 
]