如何在Bash中高效将API返回的JSON数组转为可交互菜单?
在Bash中解析JSON生成选择菜单并处理用户输入
我从API获取了如下JSON数组数据:
[{"name":"***.com","id":"***-0a5864441f49","type":"NATIVE"},{"name":"***.de","id":"***-0a5864441f49","type":"NATIVE"},{"name":"***.com","id":"***-0a5864440f67","type":"NATIVE"},{"name":"***.de","id":"***-0a5864441314","type":"NATIVE"},{"name":"***.com","id":"***-0a586444968b","type":"NATIVE"},{"name":"***.de","id":"***-0a5864441314","type":"NATIVE"},{"name":"***.de","id":"***-0a5864441f49","type":"NATIVE"},{"name":"***.de","id":"***-0a5864441f49","type":"NATIVE"},{"name":"***.de","id":"***-0a58644406ac","type":"NATIVE"},{"name":"***.de","id":"***-0a58644435f4","type":"NATIVE"}]
希望将其转换为如下格式的选择菜单:
Choose one: 1. ***.com ***-0a5864441f49 2. ***.de ***-0a5864441f49 and so on...
之后还需进一步使用用户的选择输入。请问在Bash中实现该需求的最高效方法是什么?我曾考虑使用数组,但认为用},{作为IFS分隔符不可行,尝试后也未成功。
最佳解决方案:使用jq解析JSON(高效且健壮)
手动用IFS分割JSON字符串非常不可靠,因为JSON的结构可能存在空格、转义字符等变化,容易出错。jq是Bash中处理JSON的标准工具,能精准解析结构,是最高效的方案。
完整实现代码
#!/bin/bash # 假设API返回的JSON数据已存入变量json_data json_data='[{"name":"***.com","id":"***-0a5864441f49","type":"NATIVE"},{"name":"***.de","id":"***-0a5864441f49","type":"NATIVE"},{"name":"***.com","id":"***-0a5864440f67","type":"NATIVE"},{"name":"***.de","id":"***-0a5864441314","type":"NATIVE"},{"name":"***.com","id":"***-0a586444968b","type":"NATIVE"},{"name":"***.de","id":"***-0a5864441314","type":"NATIVE"},{"name":"***.de","id":"***-0a5864441f49","type":"NATIVE"},{"name":"***.de","id":"***-0a5864441f49","type":"NATIVE"},{"name":"***.de","id":"***-0a58644406ac","type":"NATIVE"},{"name":"***.de","id":"***-0a58644435f4","type":"NATIVE"}]' # 1. 用jq解析JSON,生成带序号的菜单,同时将每个条目存入数组 mapfile -t items < <(jq -r 'to_entries[] | "\(.key+1). \(.value.name) \(.value.id)"' <<< "$json_data") # 2. 显示选择菜单 echo "Choose one:" printf '%s\n' "${items[@]}" # 3. 读取用户输入 read -p "Enter the number of your choice: " choice # 4. 验证输入并提取对应数据 if [[ "$choice" =~ ^[0-9]+$ && "$choice" -ge 1 && "$choice" -le "${#items[@]}" ]]; then selected_item="${items[$((choice-1))]}" # 提取name和id(也可以直接用jq根据索引获取原始数据) selected_name=$(jq -r ".[$((choice-1))].name" <<< "$json_data") selected_id=$(jq -r ".[$((choice-1))].id" <<< "$json_data") echo "You selected: $selected_name ($selected_id)" # 这里可以添加后续处理逻辑 else echo "Invalid choice!" exit 1 fi
关键步骤说明
mapfile+jq生成数组:jq -r 'to_entries[] | "\(.key+1). \(.value.name) \(.value.id)"':将JSON数组转为键值对,键是索引(从0开始),加1后作为菜单序号,拼接name和id生成菜单条目。mapfile -t items:将jq输出的每一行存入数组items,-t用于去掉换行符。
处理用户选择:
- 验证输入是否为有效数字,且在菜单序号范围内。
- 可以直接通过数组索引获取菜单文本,也可以再次用
jq根据索引从原始JSON中提取完整的name/id数据,适合后续业务逻辑使用。
为什么不推荐手动分割JSON?
用IFS="},{分割字符串的方法非常脆弱:
- JSON中可能存在嵌套结构、空格、转义引号等,会导致分割结果混乱。
- 如果API返回的JSON格式稍有变化(比如新增字段、调整空格),脚本就会失效。
jq是专门为JSON设计的工具,处理效率和可靠性远高于手动字符串操作。
内容的提问来源于stack exchange,提问作者Haui
相关产品推荐
相关产品推荐

