Perl排序多列数组

时间:2012-01-13 06:30:36

标签: perl sorting

hostlist.txt文件只有1个col。 prog读取hostlist.txt文件,删除重复的主机名,对列表进行排序,查找列表中每个主机的ip地址,并在终端上打印输出。

hostlist.txt

host01
host03
host02
host01
终端上的

输出

host01,192.168.1.15
host02,192.168.1.12
host03,192.168.1.33

程序:

open(HOSTFILE, "hostlist.txt") or die "Couldn't open location file: $!\n";
while ($hosts = <HOSTFILE>) {
    chomp($hosts);
    push(@hostnames, $hosts);
}
close HOSTFILE;
@hostnameUnique = uniq(@hostnames);
@hostnameUniqueSorted = sort { lc($a) cmp lc($b) } @hostnameUnique; 

foreach $hostname (@hostnameUniqueSorted){
    $ipaddr = inet_ntoa((gethostbyname($hostname))[4]);
    print "$hostname,$ipaddr\n";
}

除了输入文件newhostlist.txt有3个col之外,我想做与上面相同的事情。删除重复的主机名,排序第一个col($type),然后排序第3个col($location),然后排序第2个col($hostname),查找ip地址和打印输出。 /> 如何处理多列数组?

newhostlist.txt

dell,host01,dc2
dell,host03,dc1
hp,host02,dc1
dell,host01,dc2

输出:

dell,host03,192.168.1.33,dc1
hp,host02,192.168.1.12,dc1
dell,host01,192.168.1.15,dc2

3 个答案:

答案 0 :(得分:3)

#!/usr/bin/perl
use strict;
use warnings;

open(my $fh, '<', "newhostlist.txt") or die "Unable to open file: $!\n";

my %unique = map {$_ => 1} <$fh>;

my @data = 
    map {join",", ($_->[0], $_->[1], (@{$_->[3]}=gethostbyname($_->[1]))?inet_ntoa($_->[3][4]):'-' , $_->[2])}
    sort {$a->[0] cmp $b->[0] ||
          $a->[2] cmp $b->[2] ||
          $a->[1] cmp $b->[1]}
    map {s/^\s+|\s+$//g; [split/,/]} keys %unique;

答案 1 :(得分:3)

ETA:添加了对ipaddr查找失败的检查。

最简单的处理方法是使用菱形算子,我觉得:

use strict;
use warnings;
use ARGV::readonly;

my %seen;
while (<>) {
    chomp;  # to avoid missing newline at eof errors
    next if $seen{$_};
    $seen{$_}++; 
    my @row = split /,/, $_;
    my @host = gethostbyname($hostname); 
    my $ipaddr;
    if (@host == 0) { 
         $ipaddr = "host not found - ip not avail";
    } else {
         $ipaddr = inet_ntoa($host[4]);
    } 

    splice @row, 2, 0, $ipaddr;
    print join ",", @row;
}

使用ARGV::readonly可以更安全地使用与菱形运算符一起使用的隐式文件。

之后,只需清除使用散列已经看到的行,拆分行,在需要的地方输入所需的值,然后打印出重新组合的行。

如果您希望行中的数据更复杂,您可能希望查看csv模块,例如Text::CSV

答案 2 :(得分:0)

我建议使用一系列哈希:

.....
my ($type, $hostname, $location) = split /,/, $line;
push @records, {
    type => $type,
    hostname => $hostname,
    location => $location,
};
.....

my @records_sorted = sort { $a->{type} cmp $b->{type} || $a->{location} cmp $b->{location} || $a->{hostname} cmp $b->{hostname} } @records;
...