JavaRed
JavaRed

Reputation: 708

Parse a CSV into Perl hash in a sub and return the value passed to that sub

I try to parse a csv into hash in perl in a sub, then return value of key passed to sub as an argument. CSV file is like:

host1, 12121
host2, 34324252345
host3, 45345
host4, 56363425
host5, 3.1
hostn, 435345

And my code is like:

#!/usr/bin/perl -w
my $host_key = getValue('host1');
print $host_key;
sub getValue {
    my $host_file = 'test.csv';
    my $hostname = $_[0];
    chomp($hostname);
    my %hash;
    open my $fh, '<', $host_file or die "Cannot open: $!";
    while (my $line = <$fh>) {
        my @hostname_lines = split /,/, $line;
        my $hostname = shift @hostname_lines;
        $hash{$hostname} = \@hostname_lines;
    }
    close $fh;
    my $host_value = $hash{$hostname};
    return $host_value;
}

When I run this code, my return value would be ARRAY(0x6b72d0) but I expect a return value of 12121

Upvotes: 0

Views: 89

Answers (1)

zdim
zdim

Reputation: 66881

You build a hash with values being arrayrefs inside the while loop.

So you need to retrieve an element in that arrayref

my %host;
...
my $host_value = $host{$name}->[0];

what can also be written as

my $host_value = $host{$name}[0];

where the original array had been shifted so the number is now the first element in arrayref.


This can also be done as

while (my $line = <$fh>) {
    my ($name, @numbers) = split /\s*,\s*/, $line;
    $host{$name} = \@numbers;
}

since the first element in split's return list goes into the first scalar, and the rest into the array.


The data shows one number for a host on each line. If that is always so, no need for an arrayref

my %host;
while (my $line = <$fh>) {
    my ($name, $val) = split /\s*,\s*/, $line;
    $host{$name} = $val;
}

where /\s*,\s*/ trims spaces as well, or even

my %host = map { split /\s*,\s*/ } <$fh>;

which has the weakness of not being able to easily check expected data format.

Upvotes: 2

Related Questions