I have a file that contains some info including IP addresses like below (a line may contains more than one IP):
ip_group1,1.2.3.4,otherstring1,otherstring2,4.5.6.7
ip_group2,3.4.5.6,otherstring1
ip_group3,11.21.31.41,otherstring1,otherstring2,4.5.6.7,otherstring4,1.2.3.4,otherstring5,otherstring2,41.51.16.71
I am using this portion of the Perl code to extract the IPs, but it only extracts the first occurrence of the IP and leaves the other IPs present in the line and process the next.
use Regexp::Common qw/net/;
while (<>) {
print $1, "\n" if /($RE{net}{IPv4})/;
}
How to get all the IPs present in a line?
My expected output is below:
ip_group1,1.2.3.4,4.5.6.7
ip_group2,3.4.5.6
ip_group3,11.21.31.41,4.5.6.7,1.2.3.4,41.51.16.71
CodePudding user response:
If you match globally (//g
) in a while
loop, you can get all IP addresses:
use warnings;
use strict;
use Regexp::Common qw/net/;
while (<DATA>) {
my ($grp) = /(^\w )/;
my @ips;
while (/($RE{net}{IPv4})/g) {
push @ips, $1;
}
print join(',', $grp, @ips), "\n";
}
__DATA__
ip_group1,1.2.3.4,otherstring1,otherstring2,4.5.6.7
ip_group2,3.4.5.6,otherstring1
ip_group3,11.21.31.41,otherstring1,otherstring2,4.5.6.7,otherstring4,1.2.3.4,otherstring5,otherstring2,41.51.16.71
Prints:
ip_group1,1.2.3.4,4.5.6.7
ip_group2,3.4.5.6
ip_group3,11.21.31.41,4.5.6.7,1.2.3.4,41.51.16.71
CodePudding user response:
With a global match (/g
) in a list context all matches are returned (see it in perlretut)
while (<>) {
my @ips_line = /($RE{net}{IPv4})/g;
}
Altogether, one way
use warnings;
use strict;
use Regexp::Common qw/net/;
my @ips;
while (<>) {
my ($group) = /^([^,] )/;
my @ips_line = /($RE{net}{IPv4})/g;
push @ips, join ',', $group, @ips_line;
}
say for @ips;
Or, since push imposes list context on its operands
while (<>) {
push @ips, join ",", /^([^,] )/, /($RE{net}{IPv4})/g
}