如何在jq的walk函数中检测错误并通知外部脚本?
解决jq无法修改外部Shell变量的问题
问题根源
jq运行在独立的子进程中,和父Shell的变量空间完全隔离,所以你在jq内部尝试修改flag变量的操作,根本不会影响到Shell里的flag值——这是跨进程变量无法共享导致的。
解决方案
不需要依赖外部变量,直接让jq完成检查并通过退出码或输出内容告知Shell结果即可,以下是两种简洁的实现方式:
方式1:用any递归检查(推荐)
利用jq的any(..; 条件)语法递归遍历所有JSON节点,只要存在任意一个foo字段值不为true,就返回true,配合-e选项让jq根据输出返回对应退出码,Shell直接判断退出码即可:
if jq -e 'any(..; type == "object" and has("foo") and .foo != true)' file.json > /dev/null; then echo "ERROR: 存在foo字段值不为true的情况" exit 1 fi
-e选项:让jq在输出false时返回退出码1,输出true时返回退出码0..:递归遍历JSON的所有节点> /dev/null:屏蔽jq的标准输出,只关注退出码
方式2:用walk输出错误信息
如果你坚持要用walk,可以让jq在发现不符合条件的字段时,将错误信息写入标准错误流,然后Shell捕获这个错误输出并判断:
# 捕获jq的标准错误输出 error_msg=$(cat file.json | jq ' walk( if type == "object" and has("foo") and .foo != true then # 将错误信息写入stderr (stderr |= . + "ERROR: 发现无效的foo字段值\n") | . else . end )' 2>&1 >/dev/null) # 如果有错误输出,就打印并退出 if [[ -n "$error_msg" ]]; then echo "$error_msg" exit 1 fi
原代码的语法修正提示
你原代码里的jq语法有两处小错误:has "foo"应该写成has("foo"),if语句末尾的分号属于多余内容,不过这不是核心问题,核心还是进程隔离导致的变量无法共享。
内容的提问来源于stack exchange,提问作者lem
相关产品推荐
相关产品推荐

