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

I am racking my brain since yesterday ,so any help is truly appreciated To keep the story short, 1.I am saving the filesnames that end with .plf(key) and its lines (values)in a hash 2.and then based on a regex getting files from an RPF file 3.and then grepping every files in step2 in the values of the hash %Hash_filenames(values of this hash contains the lines of PLF) and saving the matches in another hash(Hash_filematches) and printing it. 4"load.c" is a file in RPF file and there is a line in "Loading.PLF" with load.c in it.Ideally loading.PLF (key) and the matching line with load.c(value) in it should be printed but the below code fails in the grep I believe.

Sample RPF file .\embark.c-046870;circuitPLF.flf;//server/tools/xp/files/plf/src/embar +k.c - # : 13 .\idle.cpp-051200;circuitPLF.flf;//server/tools/xp/files/plf/src/idle. +cpp - # : 14 .\load.c-059070;circuitPLF.flf;//server/tools/xp/files/plf/src/load.c +- # : 17
#!/usr/bin/perl -w use strict; use warnings; use Data::Dumper; use Cwd; #$root_dir = getcwd; my %Hash_filenames=(); my %Hash_filematches=(); my $plf; opendir(DIR, "$start_dir"); my @plf_files = grep(/\.plf$/,readdir(DIR)); # @files = </var/www/htdocs/*.html> #$start_dir = "C\:\\Program Files"; #my @plf_files = glob("$start_dir\/*.plf"); print "PLF FILES\n"; print "@plf_files\n"; #open my $match, '<',"$start_dir\\$plf_files[0]" or die "could not ope +n file' $!"; foreach my $plf (@plf_files) { chomp($plf); open my $match, '<',"$start_dir\\$plf" or die "could not open '$plf' $ +!"; my @file_lines = <$match>; $Hash_filenames{$plf}=\@file_lines; } closedir(DIR); my $file = <Crm/*.rpf>; open my $DATA, '<', $file or die "could not open '$file' $!"; my( %seen_file, %seen_vu); while (my $line = <$DATA>){ (my $file_name) = $line =~ / \\ #Match a backslash. ( #Capture the following mat +ch in $1. [^\\]+? #Match anything not a backslas +h, ) #one or more times, non gr +eedy. ; #Match a semicolon /xmsg; if ( ($file_name) and ( !$seen_file{$file_name}++ ) ) { chomp($file_name); #print "FILENAME $file_name\n"; foreach my $filename(keys %Hash_filenames) { @{ $Hash_filematches{ $filename } } = grep( (/\/\Q$file_name\E#/i + && !/\.plf/), @{ $Hash_filenames{ $filename } });------>this grep se +ems to be failing, }#for loop end }#if file_name end close $DATA; print "PRINTING MATCHED HASHES\n"; 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"; } } close $hash;

This is what i tried.I took a single file in "my $file_name = "load.c"; variable "and used the following code,the grep works and I see "Loading.PLF" and the match line with "load.c" in it getting printed in %Hash_filematches

#my $start_dir; #my $file_name = "load.c"; opendir(DIR, "$start_dir"); @plf_files = grep(/\.plf$/,readdir(DIR)); #@plf_files = glob($start_dir . '\\' . '*.plf'); print "PLF FILES\n"; print "@plf_files\n"; closedir(DIR); foreach my $plf (@plf_files) { chomp($plf); open my $match, '<',"$start_dir\\$plf" or die "could not open '$plf' $ +!"; my @file_lines = <$match>; $Hash_filenames{$plf}=\@file_lines; } open my $hash, '>', "hash.txt"; print $hash Dumper( \%Hash_filenames ); if ($file_name) { foreach my $filename(keys %Hash_filenames) { @{ $Hash_filematches{ $filename } } = grep( /\/\Q$file_name\E#/i +, @{ $Hash_filenames{ $filename } }); }------> this grep passes } #print Dumper( \%Hash_filematches ); print "PRINTING MATCHED HASHES\n"; 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: Grep on the values of a hash seems to be failing - Tricky
by kcott (Archbishop) on Nov 02, 2010 at 05:46 UTC

    I did a search for Hash_filenames on this page:

    ... my %Hash_filenames=(); ... foreach my $filename(keys %Hash_filenames) {

    So, that foreach loop will never be entered and the grep you think is failing (in some undisclosed way) will never be reached.

    -- Ken

      Ken, why do you think so?I added some debug statements in the for loop and I can see forloop being entered

        Here's the loop with the grep you think is failing as you posted it:

        foreach my $filename(keys %Hash_filenames) { @{ $Hash_filematches{ $filename } } = grep( (/\/\Q$file_name\E#/i + && !/\.plf/), @{ $Hash_filenames{ $filename } });------>this grep se +ems to be failing, }#for loop end

        There's no print statement.

        %Hash_filenames has no keys: the last occurrence set it that way: my %Hash_filenames=();

        There are two other foreach loops in your code: one looks nothing like this; the other says the grep worked.

        I suspect you're getting very frustrated: your post which you almost immediately said to ignore followed by the double posting of this one rather bears that out. Friendly advice: take a break, collect your thoughts then come back to this code when you're feeling refreshed and ready to tackle it again. Been there, done that, know what I'm talking about. :-)

        -- Ken

Re: Grep on the values of a hash seems to be failing - Tricky
by ig (Vicar) on Nov 02, 2010 at 11:09 UTC
    the below code fails in the grep I believe

    Actually, it fails long before it reaches the grep. It fails to compile:

    Global symbol "$start_dir" requires explicit package name at test.pl l +ine 10. Global symbol "$start_dir" requires explicit package name at test.pl l +ine 21. BEGIN not safe after errors--compilation aborted at test.pl line 26.

    Even accepting that you have provided incomplete code, it is difficult to help because you haven't provided a sample of the data the suspect grep is operating on.

    I note that the grep in your second sample, which you say is working, doesn't include && !/\.plf/. Maybe that is the root of your problem?

Re: Grep on the values of a hash seems to be failing - Tricky
by umasuresh (Hermit) on Nov 02, 2010 at 12:36 UTC
    You can avoid headaches if you use a debugging tool listed in one of my posts.
    Re: RegEx and Packaging Name Problem
    In this tool, there is an options to save a config file, where you can monitor data structures as you run it line by line! Installing this module in Windows is very straight forward, just use ppm install! This tool saved me not only time, but headache, heartburn...