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

Newbie so be gentle with me. I am trying to open a tab delimited file and then populate a hash. The program runs without diagnostics but running diagnostics say "uninitialized value in concatenation" But no output to file in either case. I don't understand what I need to do! The print statement is being used only to check output Any help would be much appreciated
#!/usr/bin/perl -w use strict; use diagnostics; my($line, $key, $value, $values); my %values = (); unless (open (INFILE, "inputHash.txt")){ die "Cant open input.txt\n";} # opens the file read only while (<INFILE>){ chomp; next unless (/\t/); my ($key, $value ) = split(/\t/, $_, 2); $values{$key}=$value; } close (INFILE); #close input file unless (open (OUTPUT, ">popHash.txt")){die "Cant open popHash.txt\n";} print OUTPUT "$values{$key} $value\n";

Replies are listed 'Best First'.
Re: populate hash tab delimited
by aquarium (Curate) on Mar 07, 2006 at 13:26 UTC
    the scalar $key and $value, as used in your print statement at end of script, are out of scope. you declared them with "my" inside the while loop. so outside the while loop these scalars don't exist; but your hash does as it's a global.
    the hardest line to type correctly is: stty erase ^H
Re: populate hash tab delimited
by oknow (Chaplain) on Mar 07, 2006 at 13:24 UTC

    You declare both $key and $ value before the while loop. Inside the whlie loop you declare them again, this makes the $key and $value local to the while loop. When the loop finishes those variables disappear. The $key and $ value you are using in the print statement have never been given a value.

    Your code should work if you drop the 'my' from the loop.

    Oknow
      Thanks very much
Re: populate hash tab delimited
by rhesa (Vicar) on Mar 07, 2006 at 13:24 UTC
    Remove this line (#5):
    my($line, $key, $value, $values);
    Then think about how you should iterate over %values to print its contents to OUTPUT.

    Good luck :)

      I have been trying to get that script to work for ages. Thanks to all for their input Gavin
      Would below then allow me to check the contents of the hash? while (<INFILE>){ chomp; next unless (/\t/); my ($key, $value ) = split(/\t/, $_, 2); $values{$key}=$value; foreach $key (keys %value) { print OUTPUT "$values {$key}\n"; } }
        Sort of, yes. Except for a couple of details :)

        First, by looping over the hash inside the while loop, you print out every value several times: once for every line of the input file.

        Second, you haven't opened the output file yet, so you'll likely get an error.

        The foreach loop itself is almost right, but you'd want to move it outside the while loop:

        #!/usr/bin/perl -w use strict; use diagnostics; my %values = (); unless (open (INFILE, "inputHash.txt")){ die "Cant open input.txt: $!" +;} # opens the file read only while (<INFILE>){ chomp; next unless (/\t/); my ($key, $value ) = split(/\t/, $_, 2); $values{$key}=$value; } close (INFILE); #close input file unless (open (OUTPUT, ">popHash.txt")){die "Cant open popHash.txt: $!" +;} foreach my $key (keys %values) { print OUTPUT "$key $values{$key}\n"; }