perumal has asked for the wisdom of the Perl Monks concerning the following question:

sub main{ my $path; my @paths; my %alarm_details; my @alarm_details; @paths = </TELECOM_PROJ_MAIN/sas/tmp/t*>; #giving the file path foreach $path(@paths){ %alarm_details = {}; open(LOG,"<$path") || die "can't open log "; $alarm_details{filepath} = $path; while (<LOG>) { /^(.*)=(.*)$/; $alarm_details{ $1 } = $2 if ($1); } push(@alarm_details,\%alarm_details); } return Dumper(@alarm_details); }
The above code reads the contents from a file and puts them in a hash.i want to reuse this hash in another method ..how do i do that?
The return statement in the above code does not give me the entire elements in the array..it jus gives me the last hash in the array..
how do i get the entire elements in the array

Janitored by Corion: Added formatting, code tags, as per Writeup Formatting Tips

2006-06-12 Retitled by Corion, as per Monastery guidelines
Original title: 'hashes'

Replies are listed 'Best First'.
Re: reuse hashes in another method
by Zaxo (Archbishop) on Jun 12, 2006 at 09:38 UTC

    You can print the Dumper output to an open file handle. Read back with do.

    You have two errors there which needs to be corrected. You need make the hash value assignment conditional on a fresh match. As you have it, $1 will still be defined forever after the first match. That will do no great harm, but it could be a lot of lost motion. It's a good habit to get into when using regex backreferences.

    while (<LOG>) { $alarm_details{ $1 } = $2 if /^(.*)=(.*)$/; }
    The other error is that Dumper needs a reference to the array, not the array itself.
    { open my $fh, '>', 'hash.i' or die $!; print $fh Dumper(\@alarm_details); }
    To read the Dumper file back:
    my $alarm_details_ref = do '/path/to/hash.i';
    or,
    my @old_alarm_details = @{do '/path/to/hash.i'};

    (Added) Ha! I thought you wanted a file, 'hash.i'. To simply make the hash available without persistence, either return the reference as suggested above (preferred), or make @alarm_details a global package variable.

    After Compline,
    Zaxo

Re: reuse hashes in another method
by Samy_rio (Vicar) on Jun 12, 2006 at 09:33 UTC

    Hi perumal, Try This,

    use strict; use warnings; use Tie::IxHash; use Data::Dumper; my ($alarm_details) = &main(); print Dumper @$alarm_details; sub main{ my @alarm_details; my @paths = qw(c:/test/sample.xml c:/test/sample1.xml); #giving th +e file path foreach my $path (@paths){ my %alarm_details; #Declare Each time instead of setting nu +ll value tie %alarm_details, "Tie::IxHash"; #for Hash in order open(LOG,"<$path") || die "can't open log "; $alarm_details{$path} = $path; while (<LOG>) { chomp; /^(.*)=(.*)$/; $alarm_details{ $1 } = $2 if ($1); } push(@alarm_details,\%alarm_details); } return \@alarm_details; }

    Updated : Thanks Joost

    Regards,
    Velusamy R.


    eval"print uc\"\\c$_\""for split'','j)@,/6%@0%2,`e@3!-9v2)/@|6%,53!-9@2~j';

Re: reuse hashes in another method
by McDarren (Abbot) on Jun 12, 2006 at 09:46 UTC
    "..does not give me the entire elements in the array..it jus gives me the last hash in the array.."

    Well, that's because you clobber the %alarm_details hash on each iteration.

    Personally, I think you could do away with the @alarm_details array altogether and just use a HoH. Also, I'd go for a split rather than using a regexp, and split the lines directly into named variables. Something like this (untested):

    my %alarm_details; my @files = </TELECOM_PROJ_MAIN/sas/tmp/t*>; foreach my $file (@files) { open LOG, "<", $path or die "Can't open $file:$!\n"; $alarm_details{filepath} = $file; while (<LOG>) { chomp; my ($key, $value) = split /=/, $_; $alarm_details{filepath}{$key} = $value if ($key); } close LOG; }

    Also note that I changed @paths to @files, which seems to be more appropriate. And, the 3 argument form of open is better practise, as is checking $! upon failure.

    One more thing to note is that the above code would throw "uninitialised value" warnings on any lines that had no data to the right-side of the equals (=). But you could get rid of that by explictitly checking for both $key and $value on each iteration.

    Hope this helps,
    Darren :)