如何使用yq基于动态变量实现跨文件数组包含匹配查询
配置文件字段包含关系校验实现
现有配置文件
- JSON格式配置文件
sample.json,内容如下:
[ { "id": "1", "name": "default", }, { "id": "2", "name": "name2", }, { "id": "3", "name": "name3", } ]
- YAML格式配置文件
target.yaml,内容如下:
- name: default webhookurl: "http://localost:9091/te" - name: default1 webhookurl: "http://localost:9091/tee"
核心需求
提取target.yaml中所有name字段的值,逐一判断值是否存在于sample.json的name字段集合中,输出每个值的校验结果,期望输出格式为:
default -> True default1 -> false
已尝试的无效写法
- 直接执行单文件查询命令:
yq e '. | .[].name | contains("default","default1")' sample.json,输出结果不符合预期 - shell变量传参方案:
- 执行
myarr=$(yq e '. | .[].name ' target.yaml)将target.yaml的name字段存入shell变量myarr - 分别执行
yq e '. | .[].name | contains(myarr)' sample.json、yq e '. | .[].name | contains(env(myarr))' sample.json,两种写法均运行失败
- 执行
可运行实现方案
使用mikefarah/yq v4及以上版本,单条命令即可完成校验,不需要额外中转变量:
yq eval-all ' # 读取sample.json中所有name字段存为参考数组 (load("sample.json") | map(.name)) as $ref_list | # 遍历target.yaml的每一项,拼接输出判断结果 .[] | "\(.name) -> \(if $ref_list contains .name then "True" else "false" end)" ' target.yaml
之前写法的错误原因
contains函数用法理解错误:该函数默认判断传入参数是否为当前字符串的子串,并非判断元素是否存在于集合中,且直接传入多个字符串参数不符合函数语法要求- shell变量传参逻辑错误:提取的shell变量是多行字符串格式,没有处理为yq可识别的数组结构,且变量引用方式不符合yq的变量传入规则,会触发未定义变量报错
内容的提问来源于stack exchange,提问作者Dnyaneshwar Jadhav
相关产品推荐
相关产品推荐

