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

Greetings, Monks!

I am a relatively new Perl programmer. One of my variables is becoming undefined, and I do not know why.

I wanted a script to read in a series of csv files with column headers, and create a main hash, $file_data, to store an array of records for each file. Each 'record' is a hash reference. Everything was working yesterday, but I must have done something, because now the main hash becomes empty after the loop that reads the files.

Here is the code:

@rem = 'source http://www.dostips.com @CD/d"%~dp0"&perl -s "%~nx0" %*&Exit/b&:'; #perl script starts below here use Warnings; use Strict; use File::Basename; my %file_data; my @field_headers = (); open(OUT, ">inbound.txt") || die("can't open output file: $!"); # read all of the files dropped onto the batch file while (<>) { #grab and save the column headers on the first line if($. == 1) { @field_headers = @{split_csv_string($_)} ; # read the rest of the lines. each 'record' is a hash with the # field name as the key. each 'record' is added to the array of # records for that file } else { my %record; my $i = 0; foreach my $field_val ( @{split_csv_string($_)} ) { $record{ $field_headers[$i] } = $field_val; $i++; } # ****** $file_data IS OK HERE! ****** push @{ $file_data{ $ARGV } }, \%record; } # reset line numbering on each input file if (eof) { # Not eof(). close(ARGV); @field_headers = (); } } # ****** $file_data IS BLANK HERE! ******

Replies are listed 'Best First'.
Re: Why Does My Hash Become Undefined?
by Anonymous Monk on Apr 07, 2011 at 20:18 UTC
    strict/warnings are not Strict/Warnings
    $ perl -MStrict -e 1 Incorrect use of pragma 'strict' at -e line 0. Compilation failed in require. BEGIN failed--compilation aborted. $ perl -MWarnings -e 1 Incorrect use of pragma 'warnings' at -e line 0. Compilation failed in require. BEGIN failed--compilation aborted.
Re: Why Does My Hash Become Undefined?
by locked_user sundialsvc4 (Abbot) on Apr 07, 2011 at 23:09 UTC

    Perl is a case-sensitive language.   You must pay attention to capitalization of all use names.

    Also watch out for %file_data vs. $file_data.

    Seriously... one of the best development tools I ever fell in love with is Apple’s Time Machine backup system.   I absolutely fo’d-up my working directory just this morning.   No problem... back up once more (just in case I change my mind), then go back to the previous backup and ... Shazam...

    Another equally-vital tool is source-code control ... even good ol’CVS, or “git.”   Each time you make a change, you commit that change.   If you do something totally-foobar, you can revert.   If you find yourself saying (as in this case), “WTF?!?!?!,” you can use its diff tool to see exactly what changed, either between your current file and the latest commit, or between any two commits.   Even if “it’s only you,” these tools and techniques are an absolute life-saver.

      Thank you! I (obviously) did not notice the capitalized use names. I just thought I was such a wonderful programmer that I never needed any warnings! :)

Re: Why Does My Hash Become Undefined?
by InfiniteSilence (Curate) on Apr 08, 2011 at 03:39 UTC
    I rewrote a bit to get to work on command line with manually entered input:
    use warnings; use strict; use File::Basename; use Data::Dumper; my %file_data; my @field_headers = (); open(OUT, ">inbound.txt") || die("can't open output file: $!"); # read all of the files dropped onto the batch file while (<>) { if(!m/^quit$/) { #grab and save the column headers on the first line if($. == 1) { #@field_headers = @{split_csv_string($_)} ; @field_headers = split_csv_string($_) ; # read the rest of the lines. each 'record' is a hash with the # field name as the key. each 'record' is added to the array of # records for that file } else { my %record; my $i = 0; foreach my $field_val ( split_csv_string($_) ) { $record{ $field_headers[$i] } = $field_val; $i++; } # ****** $file_data IS OK HERE! ****** push @{ $file_data{ $ARGV } }, \%record; } # reset line numbering on each input file } else { close(ARGV); @field_headers = (); } } sub split_csv_string { my ($str) = @_; chop($str); return split q|,|,$str; } print Dumper %file_data;
    When I manually enter a,b,c ; 1,2,3 ; 4,5,6 (where ';' is actually an CRLF) I get:
    $VAR1 = '-'; $VAR2 = [ { 'c' => '3', 'a' => '1', 'b' => '2' }, { 'c' => '6', 'a' => '4', 'b' => '5' } ];
    I realize this output would probably look different run in your environment and the way you are running your code. You can open a filehandle for diagnostic output, run it in your environment, and see what you get and operate from there. I would personally recommend that you rewrite this code entirely and use Text::CSV in a way that you can easily debug when needed.

    Celebrate Intellectual Diversity

      Thank You! That Worked!!

      I agree that Text::CSV would have been better, but I am in a corporate environment where I cannot use anything that was not installed with ActiveState. I find myself reinventing the wheel over and over again.

Re: Why Does My Hash Become Undefined?
by CountZero (Bishop) on Apr 08, 2011 at 16:24 UTC
    And for those who are not constrained by ill-advised corporate blindness, a solution in a few lines:
    use Modern::Perl; use Text::CSV; use Data::Dumper; my $csv = Text::CSV->new () or die "Cannot use CSV: ".Text::CSV->error +_diag (); open my $fh, "<", 'test.csv'; $csv->column_names ($csv->getline ($fh)); my $arrayref = $csv->getline_hr_all ($fh); say Dumper(\$arrayref); # __DATA__ # First,Second,Third # 1,2,3 # One,Two,Three # Een,Twee,Drie

    Output:

    $VAR1 = \[ { 'Second' => '2', 'Third' => '3', 'First' => '1' }, { 'Second' => 'Two', 'Third' => 'Three', 'First' => 'One' }, { 'Second' => 'Twee', 'Third' => 'Drie', 'First' => 'Een' } ];

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

Re: Why Does My Hash Become Undefined?
by Anonymous Monk on Apr 08, 2011 at 13:09 UTC

    Thank you, Monks!

    I am the only dude using Perl for this rather large UAT project, and I had nobody to turn to. I am trying to sell Perl as a useful technology, but I had egg on my face when my scripts did not run.

    I owe you all some sort of caffeinated food product!