当标签名称不存在时 jq 输出为空

jq output is empty when tag name does not exist

当我 运行 jq 命令从 amazon cli 解析 json 文档时,我遇到了以下问题。

我正在解析 IP 地址和名为“环境”的标签。实例中的环境标签不存在,因此不会给我任何结果。

这是 AWS CLI 返回的相关输出示例

{
  "Reservations": [
    {
      "Instances": [
        {
          "PrivateIpAddress": "10.0.0.1",
          "Tags": [
            {
              "Key": "Name",
              "Value": "Balance-OTA-SS_a"
            },
            {
              "Key": "Environment",
              "Value": "alpha"
            }
          ]
        }
      ]
    },
    {
      "Instances": [
        {
          "PrivateIpAddress": "10.0.0.2",
          "Tags": [
            {
              "Key": "Name",
              "Value": "Balance-OTA-SS_a"
            }
          ]
        }
      ]
    }
  ]
}

我正在运行执行以下命令

aws ec2 describe-instances --filters "Name=tag:Name,Values=Balance-OTA-SS_a" | jq -c '.Reservations[].Instances[] | ({IP: .PrivateIpAddress, Ambiente: (.Tags[]|select(.Key=="Environment")|.Value)})'

## output
empty

即使环境标签不存在,如何在命令输出中显示 IP 地址?

此致,

您可以使用 if ... then ... else ... end 构造,或 //。例如:

.Reservations[].Instances[]
| {IP: .PrivateIpAddress} + 
  ({Ambiente: (.Tags[]|select(.Key=="Environment")|.Value)}
   // null)

让我们假设这个输入:

{
  "Reservations": [
    {
      "Instances": [
        {
          "PrivateIpAddress": "10.0.0.1",
          "Tags": [
            {
              "Key": "Name",
              "Value": "Balance-OTA-SS_a"
            },
            {
              "Key": "Environment",
              "Value": "alpha"
            }
          ]
        }
      ]
    },
    {
      "Instances": [
        {
          "PrivateIpAddress": "10.0.0.2",
          "Tags": [
            {
              "Key": "Name",
              "Value": "Balance-OTA-SS_a"
            }
          ]
        }
      ]
    }
  ]
}

这是由 describe-instances return编辑的格式,但删除了所有不相关的字段。

请注意,标签始终是一个对象列表,每个对象都有一个 Key 和一个 Value。这种格式完美 for from_entries,可以将这个标签列表转化为方便的映射对象。试试这个:

.Reservations[].Instances[] |
{
  IP: .PrivateIpAddress,
  Ambiente: (.Tags|from_entries.Environment)
}
{"IP":"10.0.0.1","Ambiente":"alpha"}
{"IP":"10.0.0.2","Ambiente":null}

这回答了如何去做。但是您可能想了解为什么您的方法不起作用。

.Reservations[].Instances[] |
{
  IP: .PrivateIpAddress,
  Ambiente: (.Tags[]|select(.Key=="Environment")|.Value)
}

您在标签上使用的 .[] 过滤器可以 return 零个或多个结果。同样,select 过滤器可以消除部分或全部项目。当您在 内部 对象构造函数(从 {} 的表达式)应用此 时,您将导致创建整个对象的次数可变.在使用这些过滤器的地方需要非常小心,因为通常这根本不是您想要的。通常您想要执行以下操作之一:

  • 将 return 倍数结果的表达式包装在数组构造函数 [ ... ] 中。这样就不会输出父对象可能为零次或多次,而是一次输出它包含一个可能有零个或多个项目的数组。例如。
    [.Tags[]|select(.Key=="Environment")]
    
  • map 应用于数组以使其保持数组但处理其内容,例如
    .Tags|map(select(.Key=="Environment"))
    
  • 应用 first(expr) 以仅捕获表达式发出的第一个值。如果表达式可能发出零项,您可以使用逗号运算符提供默认值,例如
    first((.Tags[]|select(.Key=="Environment")),null)
    
  • 应用一些其他的数组级函数,例如from_entries
    .Tags|from_entries.Environment