如何修正Bash脚本以从JSON提取lastKeepAlive值或输出NULL
修复Bash脚本实现JSON中name行后匹配lastKeepAlive值的需求
需求回顾
逐行读取JSON文件,当遇到包含"name"的行时,检查下一行是否为"lastKeepAlive"行:
- 若是,输出该行对应的数值
- 若否,输出
NULL
常见问题分析
原脚本通常会出现以下问题:
- 未正确标记
name行的状态,导致下一行判断逻辑混乱 - 正则匹配未考虑JSON键值对中的空格、引号等格式细节
- 未处理文件末尾可能的不完整行
修正后的Bash脚本
假设你的JSON文件结构类似如下(以数组形式为例):
[ { "name": "device-01", "lastKeepAlive": "2024-06-01 14:30:00", "status": "online" }, { "name": "device-02", "status": "offline" }, { "name": "device-03", "lastKeepAlive": "2024-06-01 16:45:00" } ]
使用以下脚本可实现需求:
#!/bin/bash # 标记是否刚匹配到含"name"的行 found_name=0 while IFS= read -r line || [[ -n "$line" ]]; do # 若刚匹配到name行,处理当前行(即name的下一行) if [[ $found_name -eq 1 ]]; then # 匹配lastKeepAlive键值对,提取引号内的数值 if [[ "$line" =~ \"lastKeepAlive\"[[:space:]]*:[[:space:]]*\"([^\"]+)\" ]]; then echo "${BASH_REMATCH[1]}" else echo "NULL" fi # 重置标记,继续处理后续行 found_name=0 continue fi # 检查当前行是否包含"name"键 if [[ "$line" =~ \"name\" ]]; then found_name=1 fi done < your_json_file.json
脚本逻辑说明
- 用
found_name变量作为状态标记,值为1时表示上一行是含"name"的行 - 当处于
found_name=1状态时,用正则匹配当前行是否为"lastKeepAlive"的键值对:- 正则
\"lastKeepAlive\"[[:space:]]*:[[:space:]]*\"([^\"]+)\"会忽略键和值之间的任意空格,提取引号内的数值 - 匹配成功则输出提取到的值,否则输出
NULL
- 正则
- 处理完后重置状态标记,继续循环读取后续行
更可靠的替代方案(推荐)
逐行处理JSON本身存在局限性(比如JSON键值对可能写在同一行、格式缩进不固定等),如果你的环境支持jq(专门的JSON处理工具),推荐用以下命令实现,更稳定且简洁:
jq -r '.[] | .name as $name | if .lastKeepAlive then .lastKeepAlive else "NULL" end' your_json_file.json
该命令会遍历JSON数组中的每个对象,只要对象包含name键,就检查是否有lastKeepAlive字段,有则输出对应值,否则输出NULL。
内容的提问来源于stack exchange,提问作者hansoecs
相关产品推荐
相关产品推荐

