Perl中优雅统计网卡addr_info的inet/inet6地址数方法
Perl简洁统计网卡IPv4/IPv6地址数量实现
核心计数逻辑
不需要手动遍历索引累加计数器,直接用Perl原生的grep做列表筛选,配合scalar获取列表长度即可完成计数,代码简洁且语义清晰:
# 统计对应family的地址总数 my $ipv4_cnt = scalar grep { $_->{family} eq 'inet' } @{$nic->{addr_info}}; my $ipv6_cnt = scalar grep { $_->{family} eq 'inet6' } @{$nic->{addr_info}};
实现原理:
@{$nic->{addr_info}}解引用addr_info数组引用,供列表操作遍历grep代码块判断每个地址条目的family字段,返回所有匹配条件的元素列表scalar强制切换到标量上下文,直接返回匹配元素的总个数,即对应类型IP的数量
校验逻辑实现
计数完成后直接判断数量阈值,触发对应告警即可:
if ($ipv4_cnt > 1 || $ipv6_cnt > 1) { warn "not supported: 网卡". $nic->{ifname}. "存在多个同类型IP地址"; # 此处插入你的异常处理逻辑 }
可选map实现方式
如果倾向于用map实现,需要注意不匹配的条目要返回空列表而非0,否则会导致计数错误:
# map版本计数,不匹配时返回空列表会被自动忽略 my $ipv4_cnt = scalar map { $_->{family} eq 'inet' ? 1 : () } @{$nic->{addr_info}};
该写法能实现同样效果,但语义上grep本身就是为列表筛选设计的,可读性比map更好,更推荐用grep版本。
完整参考代码
包含从调用ip命令、解码JSON到校验取数的全流程:
use strict; use warnings; use JSON::PP; # 调用ip命令获取JSON格式的网卡信息,不需要分两次调用传-4/-6参数 my $raw = `LC_ALL=C /sbin/ip -j addr show eno1 2>/dev/null`; my $dev_list = decode_json($raw); my $nic = $dev_list->[0]; # 指定网卡查询时返回数组只有一个元素 # 统计地址数量 my $ipv4_cnt = scalar grep { $_->{family} eq 'inet' } @{$nic->{addr_info}}; my $ipv6_cnt = scalar grep { $_->{family} eq 'inet6' } @{$nic->{addr_info}}; # 多IP校验 if ($ipv4_cnt > 1 || $ipv6_cnt > 1) { die "not supported"; } # 提取单IP场景下的地址值 my ($ipv4) = map { $_->{local} } grep { $_->{family} eq 'inet' } @{$nic->{addr_info}}; my ($ipv6) = map { $_->{local} } grep { $_->{family} eq 'inet6' } @{$nic->{addr_info}};
内容的提问来源于stack exchange,提问作者Olivier LAHAYE
相关产品推荐
相关产品推荐

