首页 > 解决方案 > 如何使用 yq 根据子键值选择所有 YAML 键?

问题描述

我有一个这样的 YAML 文件:

$ yq '.' test.yaml
{
  "entries": {
    "entry1": {
      "enabled": true
    },
    "entry2": {
      "enabled": false
    },
    "entry3": {
      "dummy": "TEST"
    }
  }
}

我想选择所有已启用属性设置为true的条目:

$ yq '.entries | select(.[].enabled==true)' test.yaml
                         ^  ^
                         |  |
                         |  --- with enabled attribute set to true
                         ------ all entries

我希望输出是

{
  "entry1": {
    "enabled": true
  }
}

但我得到

{
  "entry1": {
    "enabled": true
  },
  "entry2": {
    "enabled": false
  },
  "entry3": {
    "dummy": "TEST"
  }
}

我做错了什么?

标签: selectconditional-statementsyq

解决方案


诀窍是将对象转换为数组,将选择应用于数组元素,然后将其转换回对象。过滤器with_entries在后台进行这些转换。它是to_entries | map(foo) | from_entries(参见jq 手册)的简写。

根据使用的 yq 实现,调用略有不同:yq - Pythonyq - Go。bash 脚本包含对这两种实现的调用。

#!/bin/bash

INPUT='
{
  "entries": {
    "entry1": {
      "enabled": true
    },
    "entry2": {
      "enabled": false
    },
    "entry3": {
      "dummy": "TEST"
    }
  }
}
'

echo "yq - Go implementation"       # https://mikefarah.github.io/yq/
yq -j e '.entries | with_entries(select(.value.enabled == true))' - <<< "$INPUT"

echo "yq - Python implementation"   # https://github.com/kislyuk/yq
yq '.entries | with_entries(select(.value.enabled == true))' <<< "$INPUT"

输出

{
  "entry1": {
    "enabled": true
  }
}

推荐阅读