带有多个 select 语句和一个数组的 jq

jq with multiple select statements and an array

我有一些 JSON 如下(我在这里过滤了输出):

[
  {
    "Tags": [
      {
        "Key": "Name",
        "Value": "example1"
      },
     {
        "Key": "Irrelevant",
        "Value": "irrelevant"
      }
    ],

    "c7n:MatchedFilters": [
      "tag: example_tag_rule"
    ],
    "another_key": "another_value_I_dont_want"
  },
  {
    "Tags": [
      {
        "Key": "Name",
        "Value": "example2"
      }
    ],

    "c7n:MatchedFilters": [
      "tag:example_tag_rule",
      "tag: example_tag_rule2"
    ]
  }
]

我想创建一个 csv 文件,其中包含名称键中的值和数组中的所有“c7n:MatchedFilters”。我做了几次尝试,但仍然无法获得我期望的输出。下面是一些示例代码和输出:

#Prints the key that I'm after.
cat new.jq | jq '.[] | [.Tags[], {"c7n:MatchedFilters"}] | .[] | select(.Key=="Name")|.Value'
"example1"
"example2"

#Prints all the filters in an array I'm after.
cat new.jq | jq -r '.[] | [.Tags[], {"c7n:MatchedFilters"}] | .[] | select(."c7n:MatchedFilters") | .[]'
[
  "tag: example_tag_rule"
]
[
  "tag:example_tag_rule",
  "tag: example_tag_rule2"
]

#Prints *all* the tags (including ones I don't want) and all the filters in the array I'm after.
cat new.jq | jq '.[] | [.Tags[], {"c7n:MatchedFilters"}] | select((.[].Key=="Name") and (.[]."c7n:MatchedFilters"))'
[
  {
    "Key": "Name",
    "Value": "example1"
  },
  {
    "Key": "Irrelevant",
    "Value": "irrelevant"
  },
  {
    "c7n:MatchedFilters": [
      "tag: example_tag_rule"
    ]
  }
]
[
  {
    "Key": "Name",
    "Value": "example2"
  },
  {
    "c7n:MatchedFilters": [
      "tag:example_tag_rule",
      "tag: example_tag_rule2"
    ]
  }
]

我希望这是有道理的,如果我遗漏了什么,请告诉我。

您的尝试没有奏效,因为您从 [.Tags[], {"c7n:MatchedFilters"}] 开始构建一个包含所有标签的数组和一个包含过滤器的对象。然后你会努力寻找一种方法来一次处理整个数组,因为它把这些不相关的东西毫无区别地混在一起。如果你一开始不把它们结合起来,你会发现它更容易!

您想找到 Key"Name" 的单个标签。这是找到它的一种方法:

first(
    .Tags[]|
    select(.Key=="Name")
).Value as $name 

通过使用变量绑定,我们可以将其保存以备后用,而不必担心单独构建数组。

你说(在评论中)你只想用空格连接过滤器。你可以很容易地做到这一点:

(
    ."c7n:MatchedFilters"|
    join(" ")
) as $filters

您可以将所有这些组合在一起,如下所示。请注意,每个变量绑定都会使输入流保持不变,因此很容易组合所有内容。

jq --raw-output '
    .[]|

    first(
        .Tags[]|
        select(.Key=="Name")
    ).Value as $name|

    (
        ."c7n:MatchedFilters"|
        join(" ")
    ) as $filters|

    [$name, $filters]|

    @csv

希望这足够容易阅读并将每个概念分开。我们将数组分解为对象流。对于每个对象,我们找到名称并将其绑定到 $name,我们连接过滤器并将它们绑定到 $filters,然后我们构建一个包含两者的数组,然后将数组转换为 CSV 字符串。

我们不需要使用变量。我们可以用一个大数组构造函数包裹表达式来查找名称和表达式来查找过滤器。但我希望你能看到这些变量让事情变得更简单、更容易理解。