如何将多层YAML/JSON递归解析为Bash变量?
实现YAML转层级命名的Bash变量
你的example.yaml文件内容如下:
networks: net: driver: overlay dockerfiles: nodeapp: | FROM node:18-alpine WORKDIR /$NAME services: registry: image: registry:2 ports: - "5000:5000" - "337:337" pinger: build: context: . dockerfile: nodeapp deploy: replicas: 3
目前你能通过yq转JSON后用jq生成顶层变量,但无法递归生成层级命名的变量(比如希望echo $services_pinger_build_dockerfile能输出nodeapp),以下是实现方法:
解决方案
使用jq的递归遍历+路径追踪功能,生成下划线连接的层级变量名,最终输出可被eval执行的赋值语句:
eval $(yq e example.yaml -j | jq -r ' def path_to_var: .path | map(tostring) | join("_"); def walk_vars: if type == "object" then .[] | walk_vars elif type == "array" then to_entries[] | (.key | tostring) as $idx | .value | setpath([$idx]; .) | walk_vars else [path_to_var, (tostring | @sh)] | join("=") end; walk_vars ')
执行后即可调用层级变量:
echo $services_pinger_build_dockerfile # 输出:nodeapp echo $networks_net_driver # 输出:overlay echo $services_registry_ports_0 # 输出:5000:5000
命令说明
path_to_var函数:将节点的路径数组(如["services", "pinger", "build", "dockerfile"])转为下划线连接的变量名;walk_vars函数:- 遇到对象时递归遍历所有子节点;
- 遇到数组时将索引加入路径,生成带索引的变量名(如
services_registry_ports_0); - 遇到基础类型(字符串、数字等)时,生成符合Bash语法的赋值语句,
@sh用于确保字符串值被正确转义;
eval执行:批量运行jq输出的赋值语句,将变量导入当前Shell环境。
内容的提问来源于stack exchange,提问作者Lee
相关产品推荐
相关产品推荐

