如何使用jq查找某个键的所有路径

chr*_*sst 7 json key extract jq

在一个非常大的嵌套json结构中,我试图找到以键结尾的所有路径.

例如:

{
  "A": {
    "A1": {
      "foo": {
        "_": "_"
      }
    },
    "A2": {
      "_": "_"
    }
  },
  "B": {
    "B1": {}
  },
  "foo": {
    "_": "_"
  }
}
Run Code Online (Sandbox Code Playgroud)

将按以下方式打印:["A","A1","foo"],["foo"]


不幸的是,我不知道键的嵌套级别会出现什么级别,因此我无法通过简单的选择来解决问题.我已经接近了jq '[paths] | .[] | select(contains(["foo"]))',但输出包含任何包含foo的树的所有排列.输出:["A", "A1", "foo"]["A", "A1", "foo", "_"]["foo"][ "foo", "_"]

如果我可以保留原始数据结构格式但只是过滤掉所有不包含密钥的路径(在这种情况下,"foo"下的子树不需要隐藏),则可以获得奖励积分.

pea*_*eak 12

随你输入:

$ jq -c 'paths | select(.[-1] == "foo")' 
["A","A1","foo"]
["foo"]
Run Code Online (Sandbox Code Playgroud)

奖励积分:

(1)如果你的jq有tostream:

$ jq 'fromstream(tostream| select(.[0]|index("foo")))'
Run Code Online (Sandbox Code Playgroud)

或者更好的是,由于您的输入很大,您可以使用jq -n --stream此过滤器的流解析器():

fromstream( inputs|select( (.[0]|index("foo"))))
Run Code Online (Sandbox Code Playgroud)

(2)你的jq是否有tostream:

. as $in
| reduce (paths(scalars) | select(index("foo"))) as $p
    (null; setpath($p; $in|getpath($p))))
Run Code Online (Sandbox Code Playgroud)

在所有三种情况下,输出为:

{
  "A": {
    "A1": {
      "foo": {
        "_": "_"
      }
    }
  },
  "foo": {
    "_": "_"
  }
}
Run Code Online (Sandbox Code Playgroud)

  • @themaninthewoods - 请注意,基于 shell 的字符串插值充其量是脆弱的。考虑使用 `jq --arg s "$1" ......` 代替。 (3认同)