如何在Bash管道中实现:curl输出为JSON则格式化,否则原样输出?
解决curl输出动态适配JSON格式化的问题
我来帮你搞定这个痛点!核心思路就是根据json_pp的执行结果自动切换输出方式:如果输入是合法JSON就格式化打印,否则直接输出原始内容,同时屏蔽掉json_pp的错误提示。
下面给你几种实用的解决方案,你可以根据场景选择:
方法1:利用Shell条件判断(无临时文件,最安全)
把curl的输出先保存到变量,通过json_pp的退出码判断是否为合法JSON,再决定输出方式。修改后的关键逻辑如下:
sh -c "echo 'Versions at {}': ; # 保存curl的输出到变量 output=\$(curl --fail http://...); # 测试JSON格式是否合法,屏蔽所有输出 if echo \"\$output\" | json_pp >/dev/null 2>&1; then # 合法则格式化输出 echo \"\$output\" | json_pp else # 不合法则直接输出原始内容 echo \"\$output\" fi"
替换到你的完整命令里就是:
filter "$ENVI" "$2" running | dns_ \ | xargs -L1 --max-args=1 -I{} $DEBUG_XARGS --no-run-if-empty \ sh -c "echo 'Versions at {}': ; output=\$(curl --fail http://...); if echo \"\$output\" | json_pp >/dev/null 2>&1; then echo \"\$output\" | json_pp else echo \"\$output\" fi"
优点:
- 不需要临时文件,避免了多进程并发时的文件冲突问题
- 逻辑清晰,容易理解和调整
方法2:用临时文件中转输出
通过tee把curl的输出同时写入临时文件和管道给json_pp,如果json_pp失败就读取临时文件输出:
sh -c "echo 'Versions at {}': ; # 创建唯一临时文件 tmpfile=\$(mktemp); # 同时保存输出到临时文件和传给json_pp curl --fail http://... | tee \"\$tmpfile\" | json_pp 2>/dev/null || cat \"\$tmpfile\"; # 清理临时文件 rm \"\$tmpfile\""
注意:
- 用
mktemp生成唯一临时文件,避免多个xargs进程同时操作时的文件覆盖问题 - 必须记得删除临时文件,防止磁盘空间浪费
方法3:用jq替代json_pp(更简洁)
如果你的系统上安装了jq(很多Linux发行版默认自带),可以用更简洁的写法:
sh -c "echo 'Versions at {}': ; curl --fail http://... | jq . 2>/dev/null || cat"
原理:
jq .会格式化合法的JSON并输出- 如果输入不是JSON,
jq会返回非0退出码,此时|| cat会接管并输出原始内容 2>/dev/null用来屏蔽jq的错误提示
优点:
- 代码更简洁,可读性高
- jq的JSON处理能力比json_pp更强,支持更多高级操作
关键细节说明
json_pp的退出码:当输入是合法JSON时返回0,非法时返回非0,这是我们判断的核心依据curl --fail:如果HTTP请求失败(比如4xx/5xx状态码),curl会直接返回非0退出码,此时output变量会包含curl的错误信息,最终会被直接输出(符合你的需求)- 转义处理:在
sh -c的脚本里,变量和双引号需要用反斜杠转义(比如\$output、\"),避免被外层Shell提前解析
内容的提问来源于stack exchange,提问作者Ondra Žižka
相关产品推荐
相关产品推荐

