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

Ort*_*ntz 5 jq

说我有这样的JSON:

{
  "json": [
    "a", 
    [
      "b", 
      "c", 
      [
        "d", 
        "foo", 
        1
      ], 
      [
        [
          42, 
          "foo"
        ]
      ]
    ]
  ]
}
Run Code Online (Sandbox Code Playgroud)

我想要一个jq包含foo以下内容的索引路径数组:

[
    ".json[1][2][1]",
    ".json[1][3][0][1]"
]
Run Code Online (Sandbox Code Playgroud)

我可以使用jq以及如何实现此目的吗?我试图recurse | .foo先获得比赛,但收到错误:Cannot index array with string "foo".

小智 8

首先,我不确定获得一系列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]'
Run Code Online (Sandbox Code Playgroud)

对于您的给定输入,这将返回以下输出:

[
  ["json", 1, 2, 1],
  ["json", 1, 3, 0, 1]
]
Run Code Online (Sandbox Code Playgroud)

现在,虽然它不应该是必要的,并且很可能表明您正在以错误的方式处理您遇到的任何问题,但是可以通过转换每条路径将这些数组转换为您寻找的jq路径字符串以下脚本:

".\(map("[\(tojson)]") | join(""))"
Run Code Online (Sandbox Code Playgroud)

因此,完整的脚本将是:

jq '[paths as $path | select(getpath($path) == "foo") | $path | ".\(map("[\(tojson)]") | join(""))"]'
Run Code Online (Sandbox Code Playgroud)

它的输出将是:

[
  ".[\"json\"][1][2][1]",
  ".[\"json\"][1][3][0][1]"
]
Run Code Online (Sandbox Code Playgroud)