如何在Shell脚本循环中用jq工具构建可变键的JSON?
动态生成含可变键的JSON对象
已知通过以下jq命令可创建固定键的JSON:
jq -n \ --arg v1 "Value1" \ --arg v2 "Value2" \ '{k1: $v1, k2: $v2}'
但当键为可变值时(例如执行脚本 test.sh k1=v1 k2=v2 k3=v3),循环生成的方式常出问题:要么仅输出最后一组键值对,要么输出多个独立的JSON对象,无法得到合并后的完整结果:
{ "k1": "v1" , "k2": "v2" ,"k3": "v3" }
可行解决方案
方法1:一次性构造jq参数生成完整JSON
无需循环拼接字符串,直接将所有参数转换为jq可处理的格式,一次性生成目标JSON:
#!/bin/bash # 初始化jq参数数组 jq_args=() for arg in "$@"; do # 拆分键与值 key="${arg%%=*}" value="${arg#*=}" # 添加--arg参数,将键作为变量名,值作为变量值 jq_args+=("--arg" "$key" "$value") done # 构造jq表达式,拼接所有键值对 jq_expr='{' for arg in "$@"; do key="${arg%%=*}" jq_expr+="\"$key\": \$$key, " done # 移除末尾多余的逗号和空格 jq_expr="${jq_expr%, }" jq_expr+='}' # 执行jq命令生成JSON jq -n "${jq_args[@]}" "$jq_expr"
方法2:利用jq的reduce累加键值对
先将所有参数转换为JSON数组,再通过jq的reduce函数合并为单个对象:
#!/bin/bash # 将所有参数拆解为["键1", "值1", "键2", "值2"...]的格式 args=() for arg in "$@"; do key="${arg%%=*}" value="${arg#*=}" args+=("$key" "$value") done # 用jq处理:将数组分组为键值对,再合并为单个对象 jq -n --args '[$ARGS.positional[]] | _nwise(2) | {key: .[0], value: .[1]} | reduce . as $item ({}; .[$item.key] = $item.value)' "${args[@]}"
原脚本问题分析
- 第一种写法每次循环都重新赋值
JSON_STRING,最终仅保留最后一次循环的结果。 - 第二种写法直接拼接多个独立的JSON字符串,得到的是无效的JSON结构(多个对象连续排列),并非单个完整对象。
内容的提问来源于stack exchange,提问作者junhu
相关产品推荐
相关产品推荐

