使用 jq 选择和过滤 cloudflare pagerules

selecting and filtering cloudflare pagerules with jq

我试图找到从 Cloudflare 中过滤掉一些 pagerules 数据的最佳方法,虽然我有一个解决方案,但我正在研究它有多丑陋,并认为“必须有一个更简单的方法这样做。"

我特别询问使用 jq 实现以下目标的更好方法。我知道我可以使用一些编程库来完成同样的任务,但这个问题的重点是更好地理解 jq 是如何工作的。

假设我有一长串 CloudFlare pagerules 记录,这里有一些条目作为最小示例:

{
  "example.org": [
    {
      "id": "341",
      "targets": [
        {
          "target": "url",
          "constraint": {
            "operator": "matches",
            "value": "http://ng.example.org/*"
          }
        }
      ],
      "actions": [
        {
          "id": "always_use_https"
        }
      ],
      "priority": 12,
      "status": "active",
      "created_on": "2017-11-29T18:07:36.000000Z",
      "modified_on": "2020-09-02T16:09:03.000000Z"
    },
    {
      "id": "406",
      "targets": [
        {
          "target": "url",
          "constraint": {
            "operator": "matches",
            "value": "http://nz.example.org/*"
          }
        }
      ],
      "actions": [
        {
          "id": "always_use_https"
        }
      ],
      "priority": 9,
      "status": "active",
      "created_on": "2017-11-29T18:07:55.000000Z",
      "modified_on": "2020-09-02T16:09:03.000000Z"
    },
    {
      "id": "427",
      "targets": [
        {
          "target": "url",
          "constraint": {
            "operator": "matches",
            "value": "nz.example.org/*"
          }
        }
      ],
      "actions": [
        {
          "id": "ssl",
          "value": "flexible"
        }
      ],
      "priority": 8,
      "status": "active",
      "created_on": "2017-11-29T18:08:00.000000Z",
      "modified_on": "2020-09-02T16:09:03.000000Z"
    }
  ]
}

我想要做的是提取嵌套在 constraint.value 字段中用于 always_use_https 操作的 url。目标是提取值并将它们 return 作为 json 数组。我想到的是:

jq '[                                       
        [
                [
                        [
                                .[] | .[] | select(.actions[].id | contains("always_use_https"))
                        ] | .[].targets[] | select(.target | contains("url"))
                ] | .[] | .constraint | select(.operator | contains("matches"))
        ] | .[].value 
]'

针对我们的例子,这会产生:

[
  "http://ng.example.org/*",
  "http://nz.example.org/*"
]

在 jq 中有没有更简洁的方法来实现这个?

这会根据我理解的标准产生预期的输出:

jq '.["example.org"]
    | map(select( any(.actions[]; .id == "always_use_https"))
          | .targets[]
          | select(.target == "url")
          | .constraint.value )
' cloudfare.json