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

时间:2015-12-08 20:16:08

标签: jq

说我有这样的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

2 个答案:

答案 0 :(得分:8)

首先,我不确定获得一系列jq程序的目的是什么。虽然存在这样做的手段,但它们很少是必要的; jq不提供任何类型的eval命令。

jq具有路径的概念,路径是一个字符串和数字的数组,表示JSON中元素的位置;这相当于预期输出的字符串。例如,".json[1][2][1]"将表示为["json", 1, 2, 1]。标准库包含几个使用此概念的函数,例如getpathsetpathpathsleaf_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]"
]
相关问题