如何通过 yq 中的字典值过滤列表?

How to filter list by dictionary value in yq?

我正在使用 https://mikefarah.gitbook.io/yq/。如何按特定键下列表中的特定值过滤字典列表?在下面的示例中,我想按条件“iso3166 列表包含值 'GB'”过滤布局列表。

例子

来自 xkbcli list 的 Yaml 输出(压缩),具有一种模型和三种布局

models:
- name: pc86
  vendor: Generic
  description: Generic 86-key PC

layouts:
- layout: 'ch'
  variant: ''
  brief: 'de'
  description: German (Switzerland)
  iso639: ['deu', 'gsw']
  iso3166: ['CH']
- layout: 'gb'
  variant: 'gla'
  brief: 'gd'
  description: Scottish Gaelic
  iso639: ['eng', 'gla']
  iso3166: ['GB', 'CA']
- layout: 'gb'
  variant: 'colemak'
  brief: 'en'
  description: English (UK, Colemak)
  iso639: ['eng']
  iso3166: ['GB']

所需输出:两个 'GB' 布局

- layout: 'gb'
  variant: 'gla'
  brief: 'gd'
  description: Scottish Gaelic
  iso639: ['eng', 'gla']
  iso3166: ['GB', 'CA']
- layout: 'gb'
  variant: 'colemak'
  brief: 'en'
  description: English (UK, Colemak)
  iso639: ['eng']
  iso3166: ['GB']

到目前为止我已经试过了yq ".layouts"

使用mapselect

# Selects by .layout
yq '.layouts | map(select(.layout == "gb"))'

# Selects by .iso3166[]
yq '.layouts | map(select(.iso3166[] == "GB"))'
- layout: 'gb'
  variant: 'gla'
  brief: 'gd'
  description: Scottish Gaelic
  iso639: ['eng', 'gla']
  iso3166: ['GB', 'CA']
- layout: 'gb'
  variant: 'colemak'
  brief: 'en'
  description: English (UK, Colemak)
  iso639: ['eng']
  iso3166: ['GB']

您需要使用 iso3166 列表中的 select 来查看是否存在 "GB" 的匹配项。要更新原始 layouts 列表,请使用 |= 而不是 |

yq '.layouts | map(select( .iso3166[] == "GB" ))'

注意:自4.18.1起,yq的'eval/e'命令为默认命令,不再需要指定。