You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 06:35:30