通过匹配多个对象,使用jq过滤JSON对象列表

时间:2015-11-28 16:46:42

标签: json jq

我正在尝试过滤'aws elb describe-tags'的输出,并通过匹配三个标记来获取LoadBalancerName。我没有看到如何选择对象列表的特定元素并比较键和值。我有三个要反对的对象,如果它们都匹配,我需要返回LoadBalancerName。

以下是三个负载均衡器的示例输出,其中只有一个具有正确的标记集。

{
    "TagDescriptions": [
        {
            "Tags": [
                {
                    "Value": "production",
                    "Key": "environment"
                },
                {
                    "Value": "widget",
                    "Key": "service"
                },
                {
                    "Value": "widget_xyz",
                    "Key": "customer_prefix"
                },
                {
                    "Value": "widget_xyz-widget-production",
                    "Key": "Name"
                }
            ],
            "LoadBalancerName": "widget-xyz-widget-prod"
        },
        {
            "Tags": [
                {
                    "Value": "widget-xyz-stage-widget-ConsulStack-DKJSADKJS",
                    "Key": "aws:cloudformation:stack-name"
                },
                {
                    "Value": "stage",
                    "Key": "environment"
                },
                {
                    "Value": "arn:aws:cloudformation:us-east-1:123456789:stack/widget-xyz-stage-widget-ConsulStack-DKJSADKJS/d46ad520-92e7-11e5-a975-500150b34c7c",
                    "Key": "aws:cloudformation:stack-id"
                },
                {
                    "Value": "widget",
                    "Key": "service"
                },
                {
                    "Value": "widget_xyz",
                    "Key": "customer_prefix"
                },
                {
                    "Value": "ELB",
                    "Key": "aws:cloudformation:logical-id"
                },
                {
                    "Value": "widget_xyz-widget-stage",
                    "Key": "Name"
                }
            ],
            "LoadBalancerName": "widget-xyz-ELB-SDKJSDKJSADKJAS"
        },
        {
            "Tags": [
                {
                    "Value": "widget-xyz-prod-widget-ConsulStack-DLFJEIJNWDKD",
                    "Key": "aws:cloudformation:stack-name"
                },
                {
                    "Value": "prod",
                    "Key": "environment"
                },
                {
                    "Value": "arn:aws:cloudformation:us-east-1:123456789:stack/widget-xyz-prod-widget-ConsulStack-DLFJEIJNWDKD/ab2292f0-9398-11e5-b0f6-50d501114c2c",
                    "Key": "aws:cloudformation:stack-id"
                },
                {
                    "Value": "widget",
                    "Key": "service"
                },
                {
                    "Value": "widget_xyz",
                    "Key": "customer_prefix"
                },
                {
                    "Value": "ELB",
                    "Key": "aws:cloudformation:logical-id"
                },
                {
                    "Value": "widget_xyz-widget-prod",
                    "Key": "Name"
                }
            ],
            "LoadBalancerName": "widget-xyz-ELB-SKDJSKDJSAKDJAS"
        }
    ]
}

我已经成功实现了我的查询,但不安全。只要任何三个值与我的搜索模式匹配,它就会返回LoadBalancerName。我想搜索特定的密钥,然后比较值。

这是我在gist上的snippit上成功的不安全查询。它返回widget-xyz-widget-prod,这是我想要的参数。

jq --raw-output '.TagDescriptions[] | select(.Tags[].Value=="widget_xyz") | select(.Tags[].Value=="widget") | select(.Tags[].Value=="production") | .LoadBalancerName'

如果所有三个条件都成立,它应该返回:

Key == "service" && Value == "widget"
Key == "environment" && Value == "production"
Key == "customer_prefix" && Value == "widget_xyz"

正如您在上面的查询中所看到的,我只是在比较价值。

更新:我已经能够构建一个过滤来阻止来自一个对象的Key和Value匹配的查询,但我仍然在努力匹配多个对象。

.TagDescriptions[] | select(.Tags[].Key=="customer_prefix" and .Tags[].Value == "widget_xyz") | .LoadBalancerName

另一个更新:好的,所以,我已经能够一起破解查询。我觉得好像我仍然错过了一个难题,使用jq的一些我尚未理解的光滑功能可以大大简化这个查询。

.TagDescriptions[] | [select(.Tags[].Key == "customer_prefix" and .Tags[].Value == "widget_xyz")][] | [select(.Tags[].Key == "environment" and .Tags[].Value == "production")][] | [select(.Tags[].Key == "service" and .Tags[].Value == "widget")][] | .LoadBalancerName

2 个答案:

答案 0 :(得分:2)

<body> <div class="top-navbar"> <div class="icons"> <div class="pic"> <i class="fa fa-user fa-2x" id="top-nav-img"></i> </div> <div class="pic"> <i class="fa fa-info fa-2x" id="top-nav-img"></i> </div> </div> </div> </body>数组非常适合创建一个易于访问的对象。让事情变得简单,并且这样做。然后,访问这些值将变得非常容易。然后,您可以轻松地测试您的条件是否满意。

Tags

答案 1 :(得分:0)

有一种方法可以为jq猫提供皮肤,但是其中一个主要方法 获得一个清晰的解决方案是定义助手的能力 函数,实际上可以嵌套。无论如何,这是一个使用辅助函数的解决方案,它具有内部函数。

# Does "obj" match any of the objects in the input array?
def anymatch(obj):
  # Do all the key-value pairs in obj also occur in the input?
  def match(obj):
    . as $in
    | obj as $o
    | all( $o|keys[]; $in[.] == $o[.]);
  any(.[]; match(obj));

.TagDescriptions[]
| select( .Tags
        | (anymatch({"Key":"customer_prefix", "Value": "widget_xyz"})
           and anymatch({"Key":"environment", "Value": "production"})
           and anymatch({"Key":"service", "Value": "widget"} ) ))
| .LoadBalancerName

对于给定的输入,这会产生: "widget-xyz-widget-prod"

(顺便说一下,我认为你的“另一个更新”解决方案不是解决所述问题的有效方法,至少我理解这一点。)