tags:

views:

2266

answers:

4

I have a program in Perl I'm working on where I would need multiple keys, and a way of giving each key multiple values and follow that by being able to both read them in and write them out to an external file depending on if the key matches what the person enters into standard input. I've looked across several sites and have found information somewhat useful in reading in hashes of arrays, but not writing them out, and I would also need to be able able to add to the array in the external file.

Is this possible?

Edit: Is there a way that it could be done with starter Perl? I'm a beginner. Hashes of arrays seemed like the best way to make it work, but what I really need is a way to show multiple values for the same key while only showing the key once.

+2  A: 

Check out the module XML::Simple. It has functions XMLout that turn a hash of arbitrary items into XML and then a function XMLin that does the reverse.

David Norman
+9  A: 

Check out Data::Dumper.

For instance, this microscopic script:

#!/bin/perl -w
use strict;
use Data::Dumper;

my(%hash);

$hash{key1} = [ 1, "b", "c" ];
$hash{key2} = [ 4.56, "g", "2008-12-16 19:10 -08:00" ];

print Dumper(\%hash);

produces this output, which could clearly be edited:

$VAR1 = {
          'key2' => [
                      '4.56',
                      'g',
                      '2008-12-16 19:10 -08:00'
                    ],
          'key1' => [
                      1,
                      'b',
                      'c'
                    ]
        };

It can also be evaluated to read the data back into the program.


Extending the example to show reading in as well as printing out...Note that the code is in two main blocks, and the only variable common between the blocks is the name of the file.

#!/bin/perl -w
use strict;
use Data::Dumper;
use FileHandle;

my $file = "data.out";

{
    my(%hash);

    $hash{key1} = [ 1, "b", "c" ];
    $hash{key2} = [ 4.56, "g", "2008-12-16 19:10 -08:00" ];

    my $str = Data::Dumper->Dump([ \%hash ], [ '$hashref' ]);
    print "Output: $str";

    my($out) = new FileHandle ">$file";
    print $out $str;
    close $out;
}

{
    my($in) = new FileHandle "<$file";
    local($/) = "";
    my($str) = <$in>;
    close $in;

    print "Input: $str";

    my($hashref);
    eval $str;
    my(%hash) = %$hashref;

    foreach my $key (sort keys %hash)
    {
        print "$key: @{$hash{$key}}\n";
    }
}

The output from that script is:

Output: $hashref = {
         'key2' => [
                     '4.56',
                     'g',
                     '2008-12-16 19:10 -08:00'
                   ],
         'key1' => [
                     1,
                     'b',
                     'c'
                   ]
       };
Input: $hashref = {
         'key2' => [
                     '4.56',
                     'g',
                     '2008-12-16 19:10 -08:00'
                   ],
         'key1' => [
                     1,
                     'b',
                     'c'
                   ]
       };
key1: 1 b c
key2: 4.56 g 2008-12-16 19:10 -08:00


Jonathan Leffler
+2  A: 

Since you mentioned storing and retrieving the data, I would suggest a combination of Data::Dumper and Storable. For example:

use Data::Dumper;
use Storable;
my %test = (this => ['that', 'the', 'other'],
            that => ['this', 'the', 'other']
            );

Data::Dumper is a great way to display this data for an end user:

warn Dumper(\%test);

But for storing and retrieving, Storable makes this quite easy:

# Save the hash to a file:
store \%test, 'file.txt';
# Retrieve the hash from the file.
my $testref = retrieve('file.txt');

After the retrieve, you should find yourself with a hashref of the data from the original.

Jack M.
You probably want nstore() there in case numbers are involved. The n version stores things in network order.
brian d foy
A: 

I devote an entire chapter to lightweight persistence in Mastering Perl. You'll see most of these answers, and some other techniques.

brian d foy