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

How to use jq to find all paths to a certain key

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

例如:

{
  "A": {
    "A1": {
      "foo": {
        "_": "_"
      }
    },
    "A2": {
      "_": "_"
    }
  },
  "B": {
    "B1": {}
  },
  "foo": {
    "_": "_"
  }
}

会打印如下内容: ["A","A1","foo"],["foo"]


不幸的是,我不知道键将出现在哪一层嵌套中,所以我没能用简单的 select 弄明白。我已经接近 jq '[paths] | .[] | select(contains(["foo"]))',但输出包含任何包含 foo 的树的所有排列。 输出:["A", "A1", "foo"]["A", "A1", "foo", "_"]["foo"][ "foo", "_"]

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

根据您的输入:

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

奖励积分:

(1) 如果你的jq有tostream:

$ jq 'fromstream(tostream| select(.[0]|index("foo")))'

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

fromstream( inputs|select( (.[0]|index("foo"))))

(2) 你的jq是否有tostream:

. as $in
| reduce (paths(scalars) | select(index("foo"))) as $p
    (null; setpath($p; $in|getpath($p)))

在这三种情况下,输出都是:

{
  "A": {
    "A1": {
      "foo": {
        "_": "_"
      }
    }
  },
  "foo": {
    "_": "_"
  }
}

我遇到了同样的根本问题。

使用 (yaml) 输入如下:

developer:
  android:
    members:
    - alice
    - bob
    oncall:
    - bob
hr:
  members:
  - charlie
  - doug
this:
  is:
    really:
      deep:
        nesting:
          members:
          - example deep nesting

我想找到所有任意嵌套的组并获取它们的成员。

使用这个:

yq . | # convert yaml to json using python-yq
    jq ' 
    . as $input | # Save the input for later
    . | paths | # Get the list of paths 
        select(.[-1] | tostring | test("^(members|oncall|priv)$"; "ix")) | # Only find paths which end with members, oncall, and priv
        . as $path | # save each path in the $path variable
    ( $input | getpath($path) ) as $members | # Get the value of each path from the original input
    {
        "key": ( $path | join("-") ), # The key is the join of all path keys
        "value": $members  # The value is the list of members
    }
    ' |
    jq -s 'from_entries' | # collect kv pairs into a full object using slurp
    yq --sort-keys -y . # Convert back to yaml using python-yq

我得到这样的输出:

developer-android-members:
  - alice
  - bob
developer-android-oncall:
  - bob
hr-members:
  - charlie
  - doug
this-is-really-deep-nesting-members:
  - example deep nesting