当嵌套数组具有 key:value 匹配模式时如何忽略 json 元素?

How to ignore json elements when a nested array has an key:value matching patterm?

我一直在使用 jq(1) 并从 kubernetes api (api/v1/nodes) 得到类似的响应。

{
  "kind": "NodeList",
  "apiVersion": "v1",
  "metadata": {
    "selfLink": "/api/v1/nodes",
    "resourceVersion": "8768"
  },
  "items": [
    {
      "metadata": {
        "name": "ip-101-191-101-101.ec2.internal",
        "selfLink": "/api/v1/nodes/ip-101-191-101-101.ec2.internal",
        "uid": "2l3kje2ili-23e232-2e3ee-edwed-232398h9e3h98h",
        "resourceVersion": "8768",
        "creationTimestamp": "2020-11-19T12:27:05Z",
          },
      "spec": {
        "podCIDR": "101.191.101.101/24",
        "providerID": "aws:///us-west-1e/i-lidss9jsjldsjli",
        "taints": [
          {
            "key": "worker-group",
            "value": "prometheus",
            "effect": "NoSchedule"
          }
        ]
      }
    }
  ]
}

如您所见,数组中可以有很多。有些带有 .spec.taints ,有些则没有。有些可能是空的,有些可能是满的。

我的目标是忽略所有有污点的项目"effect": "NoSchedule"

我发现这很麻烦,因为无论我尝试什么,我已经在线搜索了好几天,我都无法让它正常工作。

我已经走到这一步了,但现在卡住了

curl api | jq -c '.items[].spec.taints |= map(select(.effect | . != "NoSchedule"))'

如有任何帮助,我们将不胜感激。

我希望这会很有用,在这个例子中有 3 个项目,一个有效:NoSchedule,一个有效:anyother,一个有 taints empty。如果正确,你只需要第二个:

{
  "kind": "NodeList",
  "apiVersion": "v1",
  "metadata": {
    "selfLink": "/api/v1/nodes",
    "resourceVersion": "8768"
  },
  "items": [
    {
      "metadata": {
        "name": "ip-101-191-101-101.ec2.internal",
        "selfLink": "/api/v1/nodes/ip-101-191-101-101.ec2.internal",
        "uid": "2l3kje2ili-23e232-2e3ee-edwed-232398h9e3h98h",
        "resourceVersion": "8768",
        "creationTimestamp": "2020-11-19T12:27:05Z"
          },
      "spec": {
        "podCIDR": "101.191.101.101/24",
        "providerID": "aws:///us-west-1e/i-lidss9jsjldsjli",
        "taints": [
          {
            "key": "worker-group",
            "value": "prometheus",
            "effect": "NoSchedule"
          }
        ]
      }
    },

  {
      "metadata": {
        "name": "ip-101-191-101-101.ec2.internal",
        "selfLink": "/api/v1/nodes/ip-101-191-101-101.ec2.internal",
        "uid": "2l3kje2ili-23e232-2e3ee-edwed-232398h9e3h98h",
        "resourceVersion": "8768",
        "creationTimestamp": "2020-11-19T12:27:05Z"
          },
      "spec": {
        "podCIDR": "101.191.101.101/24",
        "providerID": "aws:///us-west-1e/i-lidss9jsjldsjli",
        "taints": [
          {
            "key": "worker-group",
            "value": "prometheus",
            "effect": "anyother"
          }
        ]
      }
    },
    {
      "metadata": {
        "name": "ip-101-191-101-101.ec2.internal",
        "selfLink": "/api/v1/nodes/ip-101-191-101-101.ec2.internal",
        "uid": "2l3kje2ili-23e232-2e3ee-edwed-232398h9e3h98h",
        "resourceVersion": "8768",
        "creationTimestamp": "2020-11-19T12:27:05Z"
          },
      "spec": {
        "podCIDR": "101.191.101.101/24",
        "providerID": "aws:///us-west-1e/i-lidss9jsjldsjli",
        "taints": [

        ]
      }
    }


  ]

命令将是:

 jq '.items[]|select(.spec.taints[].effect!="NoSchedule") ' data1.jtxt

结果:

{
  "metadata": {
    "name": "ip-101-191-101-101.ec2.internal",
    "selfLink": "/api/v1/nodes/ip-101-191-101-101.ec2.internal",
    "uid": "2l3kje2ili-23e232-2e3ee-edwed-232398h9e3h98h",
    "resourceVersion": "8768",
    "creationTimestamp": "2020-11-19T12:27:05Z"
  },
  "spec": {
    "podCIDR": "101.191.101.101/24",
    "providerID": "aws:///us-west-1e/i-lidss9jsjldsjli",
    "taints": [
      {
        "key": "worker-group",
        "value": "prometheus",
        "effect": "anyother"
      }
    ]
  }
}

注意:我把你的数据放在一个文件里模拟输入。

根据问题,我的理解是 taints 可以有多个条目。它可以是 NoSchedule 和其他值的混合。这是 jq 如果至少存在一个具有 effectNoSchedule 的污点,则该项目将被忽略。

. as $in | $in * { items: $in.items | map(select(.spec.taints | all(.effect != "NoSchedule"))) }```

这会从 .items 数组中删除每个在 .spec.taints 中有一个数组的成员,而 .spec.taints 又至少有一个 .effect 设置为 "NoSchedule" 的对象项。在所有其他情况下,即只有 .effect 设置为其他对象的对象,或者 .taints 为空,或者根本没有 .taints,或者根本没有 .spec , 最多只有一个空对象 {} 作为 .items 数组的成员,该数组成员将被保留。

.items -= (.items | map(select(.spec.taints[].effect == "NoSchedule")?))

Demo

您可以使用 del 删除您想要的:

curl api | jq 'del(.items[] | select(.spec.taints[].effect == "NoSchedule")?)'