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

如何通过单次jq调用提取并分组AWS EC2实例的私有IP?

如何用单次jq调用完成EC2实例名与对应私有IP的分组整理?

我有两台EC2实例,每台各拥有3个私有IP。目前我通过多次jq调用成功提取并整理出JSON格式的实例名与对应IP列表:

首先执行命令:

aws ec2 describe-instances | jq '.Reservations[] | .Instances[] | (.Tags | { "iname": ( map ( select(.Value | contains("my-vm")))[] | .Value ) } ) + ( { "ip": ( .NetworkInterfaces[].PrivateIpAddress) } )' | jq -s .

得到结果:

[ { "iname": "my-vm-b", "ip": "10.11.2.145" }, { "iname": "my-vm-b", "ip": "10.11.1.146" }, { "iname": "my-vm-b", "ip": "10.11.10.144" }, { "iname": "my-vm-a", "ip": "10.11.1.9" }, { "iname": "my-vm-a", "ip": "10.11.10.125" }, { "iname": "my-vm-a", "ip": "10.11.2.85" } ]

接着追加命令:

... | jq ' group_by(.iname)[] | {(.[] | .iname): [.[] | .ip]}' | jq -s .

最终得到期望的分组结果:

[ { "my-vm-a": [ "10.11.1.9", "10.11.10.125", "10.11.2.85" ] }, { "my-vm-b": [ "10.11.2.145", "10.11.1.146", "10.11.10.144" ] } ]

我总共调用了4次jq,认为操作存在冗余,想咨询是否可以通过单次jq调用完成上述全部操作?


当然可以!单次jq调用就能搞定

你可以把所有逻辑合并到一个jq表达式里,完全避免多次调用的冗余。这里是合并后的完整命令:

aws ec2 describe-instances | jq '
.Reservations[]
| .Instances[]
| ( .Tags | map(select(.Value | contains("my-vm")))[0].Value ) as $iname
| .NetworkInterfaces[].PrivateIpAddress as $ip
| {iname: $iname, ip: $ip}
| group_by(.iname)[]
| { (.[0].iname): [.[] | .ip] }
| [.]
'

分步解释这个表达式:

  1. 遍历EC2实例数据:.Reservations[] | .Instances[] 先展开所有预约和实例,拿到单个实例对象。
  2. 提取实例名:( .Tags | map(select(.Value | contains("my-vm")))[0].Value ) as $iname 筛选出包含"my-vm"的标签值,存为变量$iname(这里默认每个实例只有一个符合条件的标签,和你原来的逻辑一致)。
  3. 提取私有IP:.NetworkInterfaces[].PrivateIpAddress as $ip 展开每个实例的所有私有IP,存为变量$ip。
  4. 构造基础键值对:{iname: $iname, ip: $ip} 生成和你第一次jq调用一样的单个实例-IP对象。
  5. 分组并整理结构:group_by(.iname)[] | { (.[0].iname): [.[] | .ip] } 按实例名分组,然后把每组转换成{实例名: [IP列表]}的结构。
  6. 包裹为数组:[.] 把每个分组对象放到数组里,得到你最终想要的结果格式。

更高效的reduce版本

还可以用reduce直接构建目标结构,跳过先生成中间数组再分组的步骤,执行效率更高:

aws ec2 describe-instances | jq '
reduce (.Reservations[] | .Instances[]) as $inst ({};
  ($inst.Tags | map(select(.Value | contains("my-vm")))[0].Value) as $iname
  | .[$iname] += $inst.NetworkInterfaces[].PrivateIpAddress
)
| to_entries | map({(.key): .value})
'

这个版本的逻辑:

  • 初始化一个空对象{}作为累加器。
  • 遍历每个实例,提取实例名$iname。
  • 把当前实例的所有私有IP直接追加到累加器中对应$iname的数组里。
  • 最后用to_entries把对象转换成键值对数组,再映射成你需要的{实例名: IP列表}格式的数组。

内容的提问来源于stack exchange,提问作者chicofranchico

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:39:01