如何从JSON文件提取指定格式的hostname到变量并用于Shell循环
问题描述
我有一个包含多条条目的大JSON文件,示例内容如下:
[ { "id": "kslhe6em", "version": "R7.8.0.00_BNK", "hostname": "abacus-ap-hf-test-001:8080", "status": "RUNNING" }, { "id": "2bkaiupm", "version": "R7.8.0.00_BNK", "hostname": "abacus-ap-hotfix-001:8080", "status": "RUNNING" }, { "id": "rz5savbi", "version": "R7.8.0.00_BNK", "hostname": "abacus-ap-hf-test-005:8080", "status": "RUNNING" } ]
我需要提取所有以abacus-ap-hf-test开头、去掉末尾:8080的hostname值,存入变量后用以下for循环调用脚本,但不知道怎么实现提取操作:
HOSTNAME="abacus-ap-hf-test-001 abacus-ap-hf-test-005" for HOSTNAME in $HOSTNAME do sh ./trigger.sh done
解决方案
直接用jq工具处理JSON数据最稳妥,这是专门的JSON解析工具,比sed/awk更能适配JSON格式的变化,不容易出错。
1. 提取目标hostname
假设你的JSON文件叫data.json,执行这条命令就能拿到处理好的hostname列表:
HOSTNAMES=$(jq -r '.[] | select(.hostname | startswith("abacus-ap-hf-test")) | .hostname | split(":")[0]' data.json)
拆解一下这条命令的作用:
.[]:遍历数组里的每一个对象select(...):只保留hostname以abacus-ap-hf-test开头的条目split(":")[0]:把hostname按冒号拆分,取前面的部分(也就是去掉:8080)-r:让输出是纯字符串,不带JSON的引号
2. 循环调用脚本
把提取到的列表放到循环里用就行:
for HOSTNAME in $HOSTNAMES do # 如果脚本需要接收hostname参数,可以改成 sh ./trigger.sh "$HOSTNAME" sh ./trigger.sh done
要是你的hostname可能带空格(本例里没有这种情况),建议用数组存,避免分割出错:
# 把结果存成数组 mapfile -t HOSTNAME_ARRAY < <(jq -r '.[] | select(.hostname | startswith("abacus-ap-hf-test")) | .hostname | split(":")[0]' data.json) # 遍历数组 for HOSTNAME in "${HOSTNAME_ARRAY[@]}" do sh ./trigger.sh "$HOSTNAME" done
没有jq的替代方法
如果系统没装jq,也可以用sed+awk凑合用,但只适合JSON格式非常规整的情况:
HOSTNAMES=$(sed -n 's/.*"hostname": "abacus-ap-hf-test-\([0-9]*\):8080".*/abacus-ap-hf-test-\1/p' data.json | tr '\n' ' ')
这条命令靠正则匹配提取符合条件的hostname,去掉:8080后用空格连起来。
内容的提问来源于stack exchange,提问作者Manoj Kumar
相关产品推荐
相关产品推荐

