如何在Bash脚本中循环遍历JSON键(解决单字符串问题)
在Bash中循环遍历JSON键的正确方法
我明白你遇到的问题——你用jq提取了JSON对象的键,但Bash把整个结果当成了单个字符串,导致循环时没法逐个处理每个键。咱们先还原一下你的场景:
你的input.json内容是:
{ "menu": { "id": "file", "value": "File", "user": { "address": "USA", "email": "user@gmail.com" } } }
你执行了这条命令:
result=$(cat input.json | jq -r '.menu | keys[]')
得到的结果是id value user,但当你用数组循环时:
for type in "${result[@]}" do echo "--$type--" done
输出却是--id value user--,所有键被当成了一个元素。
下面给你几种可靠的解决方法:
方法1:直接用while read逐行处理(最推荐)
jq的keys[]过滤器会逐行输出每个键,所以我们可以直接把jq的输出传给while read循环,这样就能逐个处理每个键:
cat input.json | jq -r '.menu | keys[]' | while read -r type do echo "--$type--" done
这个方法的好处是:
- 简单直观,不需要额外处理变量
- 能正确处理键名包含空格、特殊字符的情况
方法2:将结果存入Bash数组
如果你确实需要把键先存入数组再处理,可以利用Bash的数组赋值语法,把jq的逐行输出转换成数组元素:
# 把jq的输出按换行分割为数组元素 result=($(cat input.json | jq -r '.menu | keys[]')) for type in "${result[@]}" do echo "--$type--" done
⚠️ 注意:如果你的键名里包含空格或者特殊字符(比如*),这种方式可能会出问题,因为Bash会根据IFS(默认包含空格、制表符、换行)分割内容。所以这种方法只适合键名是简单字符串的场景。
方法3:处理带特殊字符的键名(最严谨)
如果你的JSON键可能包含空格、引号等特殊字符,可以用jq的@sh过滤器把键名转义成Shell安全的格式,再配合xargs确保每个键单独一行:
while read -r type do # 这里的type已经是转义后的安全字符串,可以直接使用 echo "--$type--" done < <(cat input.json | jq -r '.menu | keys[] | @sh' | xargs -n1)
这个方法能应对绝大多数复杂场景,确保每个键都被正确识别和处理。
内容的提问来源于stack exchange,提问作者Galet
相关产品推荐
相关产品推荐

