I have a file that looks like this:
192.168.2.2 150.25.45.7 8080
192.168.12.25 178.25.45.7 50
192.168.2.2 142.55.45.18 369
192.168.489.2 122.25.35.7 8080
192.168.489.2 90.254.45.7 80
192.168.2.2 142.55.45.18 457
I made up all the numbers.
I need to sort all these files according to the number of repetitions of the first ip. So the output would ideally look like this:
192.168.2.2 8080 369 457 3
192.168.489.2 8080 80 2
192.168.12.25 50 1
So: first ip, all the ports that were in lines with that first ip, and the number of repetitions.
I've been trying to play with the sort command and awk but I don't want to do extra work and maybe be missing out on some other straightforward solution.
Any idea? Thanks :)
A Perlish answer would look something like this.
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
my %data;
# Store IP address and port number
while (<DATA>) {
chomp;
my ($ip, undef, $port) = split;
push @{$data{$ip}}, $port;
}
# Sort (in reverse) by length of list of ports
for (sort { @{$data{$b}} <=> @{$data{$a}} } keys %data) {
say "$_ @{$data{$_}} ", scalar @{$data{$_}};
}
__DATA__
192.168.2.2 150.25.45.7 8080
192.168.12.25 178.25.45.7 50
192.168.2.2 142.55.45.18 369
192.168.489.2 122.25.35.7 8080
192.168.489.2 90.254.45.7 80
192.168.2.2 142.55.45.18 457
Output:
192.168.2.2 8080 369 457 3
192.168.489.2 8080 80 2
192.168.12.25 50 1
A Perl way:
#!/usr/bin/perl
use strict;
use warnings;
my %repeat;
while(<DATA>) {
if (/^(\d+(?:.\d+){3})\s\S+\s(\d+)$/) {
push @{$repeat{$1}}, $2;
}
}
foreach (sort {@{$repeat{$b}}<=>@{$repeat{$a}}} keys %repeat) {
my $num = @{$repeat{$_}};
print "$_ @{$repeat{$_}} $num\n";
}
__DATA__
192.168.2.2 150.25.45.7 8080
192.168.12.25 178.25.45.7 50
192.168.2.2 142.55.45.18 369
192.168.489.2 122.25.35.7 8080
192.168.489.2 90.254.45.7 80
192.168.2.2 142.55.45.18 457
output:
192.168.2.2 8080 369 457 3
192.168.489.2 8080 80 2
192.168.12.25 50 1
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With