如何使用'jq'按嵌套值过滤此json并打印父密钥标识符?

如何使用'jq'按嵌套值过滤此json并打印父密钥标识符?,json,jq,Json,Jq,假设我有这个json { "sha256:0085b5379bf1baeb4a430128782440fe636938aa739f6a5ecc4152a22f19b08b": { "imageSizeBytes": "596515805", "layerId": "", "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "tag": [ "python-3-to

假设我有这个json

{
  "sha256:0085b5379bf1baeb4a430128782440fe636938aa739f6a5ecc4152a22f19b08b": {
    "imageSizeBytes": "596515805",
    "layerId": "",
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "tag": [
      "python-3-toolchain-0.1.2"
    ],
    "timeCreatedMs": "1564631021992",
    "timeUploadedMs": "1564631067325"
  },
  "sha256:1ec7631f74a3d6d37bf9194c13854f33315260ae1f27347263dd0a8974ee82bb": {
    "imageSizeBytes": "513574770",
    "layerId": "",
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "tag": [
      "python-2-toolchain-latest"
    ],
    "timeCreatedMs": "1535447023647",
    "timeUploadedMs": "1535447042373"
  }
}
我想选择带有特定标记的图像信息(以及sha256摘要)。示例:我只想选择
tag==“python-2-toolchain-latest”
,所以它会打印这个json(使用json格式)


我已经尝试过各种方法,并且一直在研究如何引用sha256关键信息

这里有一个简单明了但高效的解决方案:

keys_unsorted[] as $k
| .[$k] as $value
| select($value.tag[0] ==  "python-2-toolchain-latest")
| {digest: $k} + $value


这是我的想法。我假设标记数组可以包含多个条目

.
|to_entries[]
|.key as $k
|.value as $v
|.value.tag[]
|select(.=="python-2-toolchain-latest")
[ { "digest": ($k) }, $v ] | add
看到峰值答案后,我更喜欢最后一行:

[ { "digest": ($k) } + $v ]

如果标记可以出现两次,那么将输出相同的记录两次。必须有更好的方法来简单地检查标记[]数组中是否有“python-2-toolchain-latest”。我的jq-foo不够强大。

一个可能的
jq
计划来实现您的目标:

# Embed the final result into an array to get a valid JSON output
[
    # Convert the input object into a list of { key, value } objects
    to_entries[]

    # Keep only the objects that contain the desired tag
    # The .tag field may contain multiple tags and the desired one can be at any position
    | select(.value.tag | contains(["python-2-toolchain-latest"]))

    # Add the key into the value object into the .digest property
    | .value.digest = .key

    # Keep only the values (the modified objects)
    | .value

# That's all, folks
]
我会用

.
| to_entries
| .[]
| select(.value.tag | contains(["python-2-toolchain-latest"]))
| { digest: .key } + .value
  • 我将您的示例数据放在一个名为
    pratama-1.json
    的文件中
  • 我运行了下面的命令并得到了这个输出。
    $ jq '. | to_entries | .[] | select(.value.tag | contains(["python-2-toolchain-latest"])) | { digest: .key } + .value' pratama-1.json
    {
      "digest": "sha256:1ec7631f74a3d6d37bf9194c13854f33315260ae1f27347263dd0a8974ee82bb",
      "imageSizeBytes": "513574770",
      "layerId": "",
      "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
      "tag": [
        "python-2-toolchain-latest"
      ],
      "timeCreatedMs": "1535447023647",
      "timeUploadedMs": "1535447042373"
    }
    
分解这个 您可以将
jq
程序视为类似于
sh
管道, 除: -使用
sh
(或
bash
),管道的每个阶段(即,
|
s)之间的每个命令都有一个字节流(通常只是文本),如下所示: 投入产出; -使用
jq
,每个阶段都有一个JSON流 值作为其输入和输出

  • 最简单的
    jq
    程序就是
    • 如果输入是JSON值
      true
      ,则输出是
      true
    • 如果输入是JSON值
      [true,3.1416,“foo”]
      (数组值),则输出相同
    • 如果输入是三个JSON值
      true
      3.1416
      “foo”
      (布尔值、数字和字符串), 然后这三个输出将是布尔值、数字和字符串
  • 在我的脚本开始时,
    仅表示输入值,在本例中为 您在问题中包含的JSON对象
  • 下一个阶段是
    到\u条目
    • 它将JSON对象转换为JSON对象的JSON数组。对于输入,例如:
      {
        "a": 3.1416,
        "b": false
      }
      
      进入如下数组:
      [
        {
          "key": "a",
          "value": 3.1416
        },
        {
          "key": "b",
          "value": false
        }
      ]
      
  • 下一个阶段是
    []
    ,它是一个
    jq
    操作符,可以将一个JSON值转换为多个:
    • 如果输入是一个JSON数组,如
      [true,3.1416,“foo”]
      ,则三个输出是 JSON值为
      true
      3.1416
      ,以及
      “foo”
    • 在我们的例子中,它打开了所有键值对象周围的JSON数组,这样我们就可以 输出值,而不是一个JSON数组输出值
  • 下一个阶段是
    选择(…)
    • 对于每个输入值,它计算括号中的表达式并“传递”该输入 如果表达式为true,则作为输出
    • 例如,对于三个输入
      true
      3.1416
      “foo”
      选择(type==“string”)
      只有一个输出:字符串
      “foo”
    • 我的
      select(…)
      有两个输入:
    • JSON对象
      {“key”:“sha256:008…”,“value”:{“imageSizeBytes”:…}
    • JSON对象
      {“key”:“sha256:1ec…”,“value”:{“imageSizeBytes”:…}
    • 在我的
      select(…)
      中,我使用了一个本身是
      jq
      管道的子表达式:
      .value.tag | contains([“python-2-toolchain-latest”])
    • 第一部分
      .value.tag
      在每个对象中生成键为
      “tag”
      的字段值。为了你的 示例数据中,每个值都是一个JSON数组
    • 包含([…])
      如果其参数JSON-array
      […])
      是该输入JSON数组值的成员。
      • 一些例子

      $jq'包含([“foo”])@AgungPratama-这只是四行代码,所以如果您使用jq手册阅读未排序的
      键、
      as
      选择
      ,以及对象添加(
      +
      )。@peak我喜欢您的解决方案,但它只找到
      “python…”
      数组中索引
      0
      处的对象。另外,我喜欢
      to_entries
      来获取键值对。@ColinFraizer-如果想要所有匹配项,只需省略
      0
      !FWIW,我选择了
      keys\u unsorted
      ,因为这会产生(稍微)更有效的解决方案。@peak谢谢!我并没有真正考虑使用<代码>选择($Value.tag)=“Python 2-TooChan-NeXT”<<代码>。它是有效的,但我很难把我的头围绕着它。它看起来像一个有两个操作数的运算符,但我想不是。
      [
        {
          "key": "a",
          "value": 3.1416
        },
        {
          "key": "b",
          "value": false
        }
      ]
      
      $ jq '. | contains([ "foo" ])' <<< '[ true, 3.1416, "foo" ]'
      true
      $ jq '. | contains([ "foo", true ])' <<< '[ true, 3.1416, "foo" ]'
      true
      $ jq '. | contains([ "foo", true, null ])' <<< '[ true, 3.1416, "foo" ]'
      false
      $ jq '. | contains([ "foo", true, false ])' <<< '[ true, 3.1416, "foo" ]'
      false
      $ jq '. | contains([ "foo", true, null ])' <<< '[ true, 3.1416, "foo" ]'
      false