如何在Bash中通过循环结合jq生成嵌套JSON数据
在Bash中用jq动态生成Linode API格式的嵌套JSON
方法1:逐次循环构建(适合逐个获取变量的场景)
如果你的场景是在循环中逐个拿到device_name(如sda)、disk_id、volume_id变量,可以通过初始化空JSON结构,每次循环用jq更新结构来实现:
# 初始化基础JSON结构 json='{"devices": {}}' # 模拟循环(实际场景替换成你的数据源,比如从文件/命令输出读取) while read -r device_name disk_id volume_id; do # 处理disk_id:空值转为null,非空保留数字类型 [[ -z "$disk_id" ]] && disk_val='null' || disk_val="$disk_id" # 处理volume_id同理 [[ -z "$volume_id" ]] && volume_val='null' || volume_val="$volume_id" # 用jq更新devices对象,添加当前设备的配置 json=$(echo "$json" | jq --arg dev "$device_name" \ --argjson did "$disk_val" \ --argjson vid "$volume_val" \ '.devices[$dev] = {"disk_id": $did, "volume_id": $vid}') done <<EOF sda 111 "" sdb "" 444 sdc 222 "" sdd 333 "" EOF # 输出最终JSON echo "$json"
关键细节:
--arg:传递字符串类型的设备名(如sda)--argjson:传递数字或null类型的ID,保证JSON类型正确(避免把数字转成字符串).devices[$dev] = ...:动态给devices对象添加键值对,支持新增或覆盖设备配置
方法2:批量构建(高效处理批量数据)
如果能一次性收集所有设备的配置数据,可以直接传给jq批量生成目标结构,无需循环,效率更高:
# 整理所有设备数据为JSON数组(实际场景可从命令输出/文件生成) devices_data='[ {"name": "sda", "disk_id": 111, "volume_id": null}, {"name": "sdb", "disk_id": null, "volume_id": 444}, {"name": "sdc", "disk_id": 222, "volume_id": null}, {"name": "sdd", "disk_id": 333, "volume_id": null} ]' # 用jq将数组转换为嵌套的devices结构 echo "$devices_data" | jq '{devices: (reduce .[] as $item ({}; .[$item.name] = {"disk_id": $item.disk_id, "volume_id": $item.volume_id}))}'
关键细节:
reduce .[] as $item ({}; ...):遍历数组中的每个设备项,逐步将空对象构建为目标devices结构- 这种方式避免了多次调用jq的开销,适合数据量较大的场景
为什么不用字符串拼接?
字符串拼接容易出现以下问题:
- 手动处理
null、引号等JSON语法细节,极易出错 - 无法保证数据类型正确(比如把数字转成字符串,Linode API可能会拒绝)
- 代码可读性差,维护成本高
内容的提问来源于stack exchange,提问作者Kalib Zen
相关产品推荐
相关产品推荐

