Home > Mobile >  Perl : Reading a hash with split line element as a key
Perl : Reading a hash with split line element as a key

Time:09-17

I am trying to manipulate a file by referencing a hash, but having a hard time passing the key to the hash.

The input file is a simple CSV,

    ATFTP1-a, brah, brah2,
    ATFTP1-J, brah, brah2,
    ATFTP1-m, brah, brah2,

I want to insert an element in the second column. The element should be a value in a hash that matches the first element as a key.

my %Ctct2Bob = (
    "ATFTP1-a" => "24" ,
    "ATFTP1-b" => "25" ,
    "ATFTP1-j" => "100" ,
    "ATFTP1-m" => "33" ,
)

while( my $line = <IN> ){
    my @linestuff = split(',',$line);
        print "@linestuff[0],";
        my $key = $linestuff[0];
        print $Ctct2Bob{$key};

        ...
        print "\n";
}

What I want is

    ATFTP1-a,24, brah, brah2,
    ATFTP1-J,100, brah, brah2,
    ATFTP1-m,33, brah, brah2,

For the life of me, I cannot print the value. I can print the element $Ctct2Bob{'ATFTP1-a'} though.

CodePudding user response:

You can use splice to insert into the middle of a list:

#!/usr/bin/env perl
use strict;
use warnings;
use feature qw/say/;

my %Ctct2Bob = (
    "ATFTP1-a" => "24" ,
    "ATFTP1-b" => "25" ,
    "ATFTP1-j" => "100" ,
    "ATFTP1-m" => "33" ,
    );

while (my $line = <DATA>){
    chomp $line;

    # Need the -1 here to preserve the empty trailing field
    my @linestuff = split /\s*,\s*/, $line, -1;

    # If the first array element exists in the hash, insert its
    # value as the new second element, else a default value. 
    if (exists $Ctct2Bob{$linestuff[0]}) {
        # Insert before the current second element (Offset 1).
        splice @linestuff, 1, 0, $Ctct2Bob{$linestuff[0]};
    } else {
        splice @linestuff, 1, 0, "Not found";
    }

    # And print the line out.
    say join(",", @linestuff);
}

__DATA__
ATFTP1-a, brah, brah2,
ATFTP1-J, brah, brah2,
ATFTP1-m, brah, brah2,

Note: I suggest switching to Text::CSV_XS to handle reading CSV data in any serious perl program, though for simple data like your sample, split on a comma can serve.

CodePudding user response:

A simple split and re-shuffle of an array does the trick.

Note: it is assumed that in %Ctct2Bob hash instead of "ATFTP1-j" => "100" , should be "ATFTP1-J" => "100" , -- based on desired output

use strict;
use warnings;
use feature 'say';

my %Ctct2Bob = (
    "ATFTP1-a" => "24" ,
    "ATFTP1-b" => "25" ,
    "ATFTP1-J" => "100" ,
    "ATFTP1-m" => "33" ,
);

while( <DATA> ){
    chomp;
    my($key,@data) = split ',';
    @data = $Ctct2Bob{$key} ? ($key,$Ctct2Bob{$key},@data) : ($key,@data);
    say join(',',@data);
}

exit 0;

__DATA__
ATFTP1-a, brah, brah2,
ATFTP1-J, brah, brah2,
ATFTP1-m, brah, brah2,

Output

ATFTP1-a,24, brah, brah2
ATFTP1-J,100, brah, brah2
ATFTP1-m,33, brah, brah2
  • Related