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

I am using activestate perl on windows. I have a simple file I am trying to load into a hash.
"caroline" 30 "andrew" 10
When I load the file and try to print the value for caroline I get the following error:

Use of uninitialized value in print at test.pl line 41, <DATAFILE> line 4.

Code to open file and print:
open DATAFILE, "<somedata" or die "Cannot open datafile: $!"; %some_new_hash = <DATAFILE>; print keys %some_new_hash; # This works fine print $some_new_hash{"andrew"}; # Causes Error
file created with following code:
use Data::Dumper; my %some_hash = ( andrew => 10, caroline => 30 ); $Data::Dumper::Terse = 1; $Data::Dumper::Indent = 1; $Data::Dumper::Useqq = 1; open DATAFILE, ">somedata" or die "Cannot open datafile: $!"; print DATAFILE Dumper %some_hash;

Replies are listed 'Best First'.
Re: uninitialized value loading into hash and printing
by liz (Monsignor) on Sep 17, 2003 at 11:20 UTC
    print $some_new_hash{"andrew"}; # Causes Error
    That's because the key you have in the hash is qq{"andrew"\n}, not qq{andrew}.

    You would need something like:

    %some_new_hash = map {chomp; s#^"##; s#"$##; $_} <DATAFILE>;
    which would lose the newlines and the double quotes of each line read from the file before being put into the hash.

    Hope this helps.

    Liz

Re: uninitialized value loading into hash and printing
by broquaint (Abbot) on Sep 17, 2003 at 11:15 UTC
    You have trailing newlines in your data (and extraneous quotes) so you need to access qq["andrew\n"] to get the "10\n". But obviously a much better idea would be to do away with the newlines altogether with a chomp and also drop the quotes e.g
    my %hash = map { chomp; s{ ^" | "$ }()xg; $_ } <DATAFILE>;
    This builds a list where every element has been chomped and the beginning and ending quote removed and then assigns it to %hash. See. map and perlre for more info.
    HTH

    _________
    broquaint

    update (broquaint): deal with the quotes too

Re: uninitialized value loading into hash and printing
by demerphq (Chancellor) on Sep 17, 2003 at 15:53 UTC

    Terse shouldnt be used in anything other than a diagnostic context. Useqq reduces the performance of your code (with certain Win32 related caveats). You dont have Purity set. The way you are dumping is at face value incorrect, and even if its deliberate is extremely prone to greivous error.

    Better to do something like:

    print DATAFILE Data::Dumper->new([\%some_hash],[qw(some_hash)]) ->Purity(1) ->Terse(0) ->Indent(1) ->Useqq(0) ->Dump();

    And then eval it into existance. Although in some conditions this is a security concern, in which case I suggest you use YAML.

    Essentially your problem is that you are trying to use a hammer to do a firehoses job. Dumper is for dumping data structures in perl code. YAML is about dumping data structures in human readable, language independent, and eval safe ways. The two purposes are very different indeed.


    ---
    demerphq

    <Elian> And I do take a kind of perverse pleasure in having an OO assembly language...