I want to check the json output of ip -j adds show eno1 in perl. I want to count how many ipv4 addr the Nic has. I still need the ipv6 info so I want to avoir running twice /usr/bin/ip command with the -4 and then -6 flag.
For now I can access to the ip information like this:
$nic->{addr_info}[0]->{local}
For each entry, the $nic->{addr_info}[$ip_info_index]->{family}
will give the IP type (inet or inet6)
In most cases 2 entries in my table: one for v4 and one for v6, but sometimes I have 2 v4 entries a and want to issue a warning "not supported" in my software.
$nic->{addr_info}[$ip_info_index]->{family}
will give the type of entry.
Is there some elegant trick using map and scalar to count how many $nic->{addr_info}[$ip_info_index]->{family}
are equal to 'inet' (and not 'inet6')
(I can loop over $ip_info_index , and increment a counter each time I see 'inet', but that seems not elegant).
DB<3> p Dumper($nic)
$VAR1 = {
'txqlen' => 1000,
'address' => '00:26:b9:7d:c0:ee',
'broadcast' => 'ff:ff:ff:ff:ff:ff',
'link_type' => 'ether',
'group' => 'default',
'mtu' => 1500,
'qdisc' => 'mq',
'flags' => [
'BROADCAST',
'MULTICAST',
'UP',
'LOWER_UP'
],
'operstate' => 'UP',
'ifindex' => 2,
'addr_info' => [
{
'valid_life_time' => 30949,
'preferred_life_time' => 30949,
'label' => 'eno1',
'family' => 'inet',
'scope' => 'global',
'noprefixroute' => bless( do{\(my $o = 1)}, 'JSON::PP::Boolean' ),
'prefixlen' => 24,
'local' => '172.16.59.72',
'broadcast' => '172.16.59.255',
'dynamic' => $VAR1->{'addr_info'}[0]{'noprefixroute'}
},
{
'family' => 'inet6',
'local' => 'fe80::226:b9ff:fe7d:c0ee',
'valid_life_time' => 4294967295,
'preferred_life_time' => 4294967295,
'prefixlen' => 64,
'scope' => 'link'
}
],
'ifname' => 'eno1'
};
for addr_info table I wantt to count how many hashes have 'family' => 'inet' (and same for 'inet6'). I need to fail if more that one ipv4 or one ipv6 is set. if you want to test on a linux system, the $nic is obtained like this:
my $ip_addr_output = `LC_ALL=C /sbin/ip -j addr 2>/dev/null`;
CodePudding user response:
I think this is what you want.
$nic->{addr_info}
is a reference to an array where each element describes one of the IP addresses attached to the interface.
So @{ $nic->{addr_info} }
dereferences that array so you can now pass it to functions that require arrays or lists. One such function is grep
which filters a list and only returns elements in the list which satisfy some criteria. We can therefore get a list of IPv4 addresses using:
grep { $_->{family} eq 'inet' } @{ $nic->{addr_info} }
If you call `grep in scalar context, it doesn't give you the list, it gives you the number of items in the list.
scalar grep { $_->{family} eq 'inet' } @{ $nic->{addr_info} }
So you can use something like this:
say "$nic->{ifname} : ", scalar grep { $_->{family} eq 'inet' } @{ $nic->{addr_info} };