Bash使用jq遍历JSON时如何访问参数匹配shops.txt对应条目?
问题原因
你的原脚本存在3个核心错误:
- 原生Bash不支持直接解析JSON对象属性,你从jq读出来的
$i是字符串格式,不能用$i.store.storeName这种语法访问JSON字段 - 原jq命令
'.[.userName, .store.storeName]'的输出是拆分后的独立字段数组,已经丢失了完整的JSON对象结构 - 没有处理
store为null的情况,直接访问store.storeName会触发jq报错
最优实现方案(单jq处理,效率更高,适合大文件)
不需要嵌套Bash循环,直接一次性把shops.txt的所有门店ID读入jq做过滤,大文件场景下性能优势非常明显:
#!/bin/bash # 读取shops.txt所有ID,转成jq可用的字符串数组,自动过滤空行 shop_list=$(jq -R -s 'split("\n") | map(select(length > 0))' shops.txt) # 一次性过滤details.json,输出匹配的用户名和门店ID jq -r --argjson shops "$shop_list" ' .[] | # 先过滤store非空的条目,避免报错 select(.store != null and .store.storeName != null) | # 完全相等匹配,如果需要模糊匹配可以替换成下面注释的代码 select(.store.storeName | IN($shops[])) | # 输出需要的字段 .userName, .store.storeName ' details.json
如果你需要的是模糊匹配(只要storeName包含目标门店ID就算匹配),把上面的
select(.store.storeName | IN($shops[]))替换为:select(.store.storeName as $name | any($shops[]; $name | contains(.)))
保留原循环逻辑的修改版
如果你一定要按逐行遍历shops的逻辑写,可以改成下面的版本,直接在jq层做匹配判断:
#!/bin/bash shops="shops.txt" while IFS= read -r currentShop || [[ -n "$currentShop" ]] do # 跳过空行 [[ -z "$currentShop" ]] && continue # 传入当前门店ID到jq做匹配,直接输出结果 jq -r --arg shop "$currentShop" ' .[] | select(.store != null and .store.storeName == $shop) | .userName, .store.storeName ' details.json done < "$shops"
该版本逻辑简单,但如果shops.txt和details.json文件都很大,会重复调用jq多次,性能远低于上面的单jq版本。
内容的提问来源于stack exchange,提问作者midi
相关产品推荐
相关产品推荐

