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

Hi, I am pasting a snippet of my code. The below code get multiple files ($file_name) and then grep for each file_name in the values of a hash(Hash_filenames) and then save the grep that matches in another hash(Hash_filematches).The issue is only the data of the last file_name is getting saved.How do I fix it?

while (my $line = <$DATA>){ (my $file_name) = $line =~ / ........... if ( ($file_name) and ( !$seen_file{$file_name}++ ) ) { foreach my $filename(keys %Hash_filenames) { @{ $Hash_filematches{ $filename } } = grep( /\/\Q$file_name\E#/i +, @{ $Hash_filenames{ $filename } });--------->@{ $Hash_filematches{ +$filename } } stores only the grep of the last $file_name }#for loop end }#if file_name end .... for my $key (keys %Hash_filematches) { my $value = $Hash_filematches{$key}; if (scalar @$value) { # check that the arrayref isn't empty print "KEY: $key\n"; print "VALUES: ", join(", ", @$value), "\n\n"; } }

Replies are listed 'Best First'.
Re: Only the last file data is getting saved in the hash
by biohisham (Priest) on Nov 07, 2010 at 07:47 UTC
    iphone post a self contained boil-down of this code that actually works and demonstrates the problem you're experiencing rather than a snippet that needs fixing..

    Another notice, in the first line while(<$DATA>), you don't really want to use names similar to special literals like DATA as your filehandle names, that may lead to confusion in case someone took up to maintain your code since DATA is connected with the special token __DATA__, read perldata->special literals and SelfLoader.

    Where does your while loop end? How did the %Hash_filenames come to existence? Depending on a test sample of your file names that you're searching, what do you expect each one of the hashes you've used to contain?

    When you say only the last file 'data' is getting saved in the hash, is 'data' reflective of the file name or the file contents? in both cases however, you may be experiencing this because something is getting overwritten with every iteration of the loop ...

    I tried cleaning up your code a little bit to get it working but I don't have any parameters to reproduce the behavior you're describing

    #!/usr/local/bin/perl use strict; use warnings; use Data::Dump qw/pp/; my %seen_file; my %Hash_filematches; my %Hash_filenames; while ( chomp(my $line = <DATA>)){ (my $file_name) = $line; if ( ($file_name) and ( !$seen_file{$file_name}++ ) ) { foreach my $filename(keys %Hash_filenames) { print "FILE NAME $file_name\n"; @{ $Hash_filematches{ $filename } } = grep( /\/\Q$file_name\E#/i +, @{ $Hash_filenames{ $filename } }); #@{ $Hash_filematches{ $filename } } = grep( (/\/\Q$file_name\E#/ +i && !/\.plf/), @{ $Hash_filenames{ $filename } });--------->@{ $Hash +_filematches{ $filename } } stores only the grep of the last $file_na +me }#for loop end }#if file_name end for my $key (keys %Hash_filematches) { my $value = $Hash_filematches{$key}; if (scalar @$value) { # check that the arrayref isn't empty print "KEY: $key\n"; print "VALUES: ", join(", ", @$value), "\n\n"; } } } print pp(\%seen_file); #print pp(\%Hash_filematches); #print pp(\%Hash_filenames); __DATA__ file1 file2 file2 file3

    Take it from here and read How di I post a question effectively?


    Excellence is an Endeavor of Persistence. A Year-Old Monk :D .

      Not certain but may be i should save the data below in an array reference,not in an array??

      @{ $Hash_filematches{ $filename } } = grep( /\/\Q$file_name\E#/i +, @{ $Hash_filenames{ $filename } });
        Not certain but may be i should save the data below in an array reference,not in an array??

        You already are

        $ perl -MData::Dump::Streamer -e" $f{f} = [ grep /\d/ , 1 ..4 ]; Dum +p( \%f ); " $HASH1 = { f => [ 1, 2, 3, 4 ] }; $ perl -MData::Dump::Streamer -e" @{ $f{f} } = grep /\d/ , 1 ..4; Dump +( \%f ); " $HASH1 = { f => [ 1, 2, 3, 4 ] };
Re: Only the last file data is getting saved in the hash
by Anonymous Monk on Nov 07, 2010 at 07:28 UTC
    Hi, I am pasting a snippet of my code.

    For future reference, as How (Not) To Ask A Question would say, you should clean your room :) write a small program to demonstrate your problem and include sample data :)

    The issue is only the data of the last file_name is getting saved.How do I fix it?

    Three possibilities

    • all the filenames are the same filename (your data is bonkers)
    • $filename is empty (your regex is failing)
    • something else in your code obliterates $filename or something :)
    As Basic debugging checklist suggests, if you sprinkle warn "filename($filename) "; at various points in your code, maybe even a Dump, you can pinpoint where your assertions fail.
    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: Only the last file data is getting saved in the hash
by kcott (Archbishop) on Nov 07, 2010 at 07:25 UTC

    Try doing this:

    my $grepped = grep(... print $grepped, "\n";

    That will tell you if the data is being overridden or if you're just retrieving the same data each time.

    You could also help yourself by tidying up your code (see perlstyle) so you can read it more easily.

    Another thing you can do is choose better variable names: using $filename and $file_name is just asking for trouble.

    -- Ken

      cleaned up the code a bit.Data is getting overridden for sure