使用CSV更新JSON文件的jq命令sponge写入失败问题排查
问题分析与解决方案
你的命令主要有三个核心问题,导致sponge无法正确更新文件:
问题点
- 未跳过CSV表头:第一行
header "a", "b"会被read读取,导致无效的匹配操作,甚至干扰后续处理 - CSV引号未处理:read读取的
f1和f2带着原始双引号(比如"a11"),而JSON中.b的值是不带引号的b1,两者无法匹配 --argjson误用:--argjson用于传递JSON格式的参数,但你要传递的是普通字符串,应该用--arg
改进方案一:修复循环逻辑
先处理CSV的表头和引号,再循环执行jq更新:
# 跳过表头行 → 移除所有双引号 → 逐行读取处理 tail -n +2 changes.csv | sed 's/"//g' | while IFS="," read -r f1 f2 do # 用--arg传递纯字符串参数,匹配JSON中的值 jq --arg k1 "$f1" --arg k2 "$f2" '(.[] | select(.b == $k2) | .a) |= $k1' sample.json | sponge sample.json done
改进方案二:一次性高效处理(推荐)
避免循环多次读写文件,先把CSV转成键值映射,再用jq一次性完成更新:
# 将CSV转换为{b值: a新值}的JSON映射,再批量更新JSON文件 jq -n --argfile json sample.json --argfile csv <(tail -n +2 changes.csv | sed 's/"//g' | jq -R 'split(",") | {key: .[1], value: .[0]}' | jq -s 'from_entries') ' $json | map(if .b as $b | $csv[$b] then .a = $csv[$b] else . end) ' | sponge sample.json
方案二说明
tail -n +2 changes.csv:跳过表头sed 's/"//g':移除所有双引号jq -R 'split(",") | {key: .[1], value: .[0]}':将每行CSV转为{key: "b1", value: "a11"}的结构jq -s 'from_entries':把所有行合并为一个映射对象{"b1":"a11", "b2":"a22", "b3":"a33"}- 最后用jq遍历原始JSON,匹配映射中的
b值来更新a字段
内容的提问来源于stack exchange,提问作者Ranit
相关产品推荐
相关产品推荐

