使用Bash和jq提取JSON中auditScore为1的父对象名与onlineScore
jq遍历JSON提取父对象名称与指定字段
问题说明
给定目标JSON数据集,需求为遍历数据,当子对象的auditScore值为1时,提取该子对象的父键名称(如audit1)以及对应的onlineScore字段值。现有Bash+jq代码可获取satelliteName,需要调整代码以实现需求,仅允许使用Bash和jq工具。
目标JSON数据
{ "storageSummary": 6.8624392E13, "audit1": { "auditScore": 1, "suspensionScore": 1, "onlineScore": 0.99743587, "satelliteName": "us2.storj.io:7777" }, "audit2": { "auditScore": 1, "suspensionScore": 1, "onlineScore": 0.9992917, "satelliteName": "saltlake.tardigrade.io:7777" }, "audit3": { "auditScore": 1, "suspensionScore": 1, "onlineScore": 0.99930555, "satelliteName": "ap1.storj.io:7777" } }
原有代码(存在无法获取父键的问题)
DS_OBJECT=$(jq -c ' .[]|select(type == "object" and has("auditScore"))' ${DS_SRC_FILE}) for row in ${DS_OBJECT}; do _jq() { echo "${row}" | jq -r "${1}" } echo -e "Processing $(_jq '.satelliteName')..." echo -e "onlineScore is $(_jq '.onlineScore') done
解决方案
原代码的核心问题是使用.[]仅提取了子对象的值,丢失了父键名称。需要通过to_entries将顶层对象转换为键值对数组,从而保留父键信息。
方案1:高效单jq输出+Bash读取(推荐)
此方式减少Bash循环内的jq调用次数,执行效率更高:
jq -r 'to_entries[] | select(.value.auditScore == 1) | "\(.key) \(.value.onlineScore) \(.value.satelliteName)"' "${DS_SRC_FILE}" | while read -r audit_key online_score satellite; do echo "Processing ${satellite}..." echo "父对象名称:${audit_key}" echo "onlineScore:${online_score}" done
方案2:兼容原循环结构的修改
如果需要保持原有代码的循环逻辑,可调整jq命令保留键值对:
DS_OBJECT=$(jq -c 'to_entries[] | select(.value.auditScore == 1)' "${DS_SRC_FILE}") for row in ${DS_OBJECT}; do _jq() { echo "${row}" | jq -r "${1}" } audit_key=$(_jq '.key') satellite=$(_jq '.value.satelliteName') online_score=$(_jq '.value.onlineScore') echo -e "Processing ${satellite}..." echo -e "父对象名称:${audit_key}" echo -e "onlineScore is ${online_score}" done
关键说明
to_entries[]:将顶层JSON对象转换为{"key": "父键名", "value": 子对象}格式的数组元素,保留父键信息select(.value.auditScore == 1):精准筛选出auditScore为1的子对象- 方案1通过jq直接拼接输出字段,Bash用
read一次性读取,避免多次调用jq产生的性能损耗
内容的提问来源于stack exchange,提问作者Burps
相关产品推荐
相关产品推荐

