Bash中通过变量传递jq路径与值时JSON嵌套赋值异常
问题原因
jq 不会自动将通过参数传入的点分隔字符串解析为嵌套路径:
- 写法
.[$path] = $value中,jq 会把$path的完整字符串值作为单个顶层键名处理,因此会新增顶层的"options.cylinders"键,不会进入嵌套层级修改 - 之前尝试的
path()函数作用是将jq路径表达式转换为路径数组,不支持赋值操作,因此会抛出函数未定义的编译错误 - 测试用的初始JSON样例存在语法错误:
year字段行、cylinders字段行末尾缺少逗号,直接执行会触发jq解析报错,测试前需要补全。
正确实现方案
所有待写入值为字符串类型的场景下,统一使用jq内置的setpath函数处理动态路径赋值,该函数接收两个参数:第一参数是由每一级键名组成的路径数组,第二参数是待写入的值。根据路径传入的格式不同,有两种常用写法:
方案1:直接传入点分隔的路径字符串
如果路径本身是点分隔的字符串(无键名包含点的特殊场景),可以先在jq内部将字符串按点拆分为路径数组,再传入setpath:
cyl="v4" path="options.cylinders" echo "$JSON" | jq --arg target_path "$path" --arg target_val "$cyl" 'setpath($target_path | split("."); $target_val)'
执行后会正确修改嵌套的options.cylinders值为v4,不会生成多余的顶层键。
方案2:传入路径数组(兼容性更强)
如果存在键名本身包含点的场景,推荐直接传入路径数组(每一级键名单独作为数组元素),避免split拆分错误。由于数组是JSON结构化类型,需要用--argjson参数传递:
cyl="v4" # 直接定义JSON格式的路径数组 path_arr='["options", "cylinders"]' echo "$JSON" | jq --argjson target_path "$path_arr" --arg target_val "$cyl" 'setpath($target_path; $target_val)'
如果使用Bash原生数组存储路径,可以先将Bash数组转换为JSON数组再传入,适配任意层级、任意合法键名的场景:
cyl="v4" # Bash原生数组定义路径,每一级键名作为一个元素 path=("options" "cylinders") # Bash数组转JSON数组 json_path=$(printf '%s\n' "${path[@]}" | jq -R . | jq -s .) echo "$JSON" | jq --argjson target_path "$json_path" --arg target_val "$cyl" 'setpath($target_path; $target_val)'
注:如果需要读取动态路径对应的值,将
setpath替换为getpath,仅传入路径数组参数即可。
内容的提问来源于stack exchange,提问作者snappy-dogs
相关产品推荐
相关产品推荐

