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

Not to new to Perl (yet I have alot to learn still), but I've never had a real open need for hashes before either, until now. Here's my question. Basically I have multiple files that I'm reading out of, where the files are the names of my hashes, so given the code (for one hash):
open(STATS, "/path/to/file"); @file = <STATS>; close STATS;
Each file will contain a one liner only, in the format of:

key|value|key1|value| and so on

And now the hash:
%file=("key" =>value, "key1" =>value);
How would I be able to read this out of @file, so that I could write the hash as:
%file=("$key" =>value, "$key1"=>value);
I was thinking of some snippits, but they would be way to long and complicated (and not needed), as I am sure there is a much easier way out there (basically I was going to run a few loops, but pointless I think). Any help would be appreciated.

Replies are listed 'Best First'.
Re: Messing with hashes
by Paladin (Vicar) on Feb 07, 2003 at 04:13 UTC
    Assuming I understand your question correctly:
    1. Each file contains only 1 line
    2. format of the line is: key_a|val_a|key_b|val_b
    3. none of the keys or values contain a |
    You could use something like:
    open(STATS, "/path/to/file") or die "Couldn't open file: $!"; my $line = scalar <STATS>; chomp $line; my %file = split /\|/, $line; close STATS;
    Notes:
    • Always remember to check the return value of your system calls like open
    • Above code will break if there are an odd number of elements in the line
    Update: Changed code to deal with trailing newline. Thanks for pointing it out ihb.
      Thanks for the help -- I got it working.
      open(STATS, "/path/to/file") or die "Couldn't open file: $!"; my %file = split /\|/, scalar <STATS>; close STATS;
      This turned out to be what I needed. As for regex... that scares me still ;) I have to do some more reading up on how that works. Thanks again =)

      Beware of the newline.

      If there is a trailing newline, and there should be according to perlfaq5/"How do I count the number of lines in a file?", you'll get an extra key "\n" with value undef. The obvious way to handle this is to first store the line in a variable, chomp() it, then split() it. A split on /[|\n]/ would work too, but I'd prefer chomp()ing.

      ihb
      I always get the willies when I see someone reading from a file into an explicit $line variable. (Also, that scalar is superfluous, of course.)

      Here's another way, using map:

      my %file = map { chomp; split /\|/ } <STATS>;

      jdporter
      The 6th Rule of Perl Club is -- There is no Rule #6.

Re: Messing with hashes
by Cody Pendant (Prior) on Feb 07, 2003 at 04:25 UTC
    Here's a regex solution, just for the hell of it.
    $line = 'key1|value1|key2|value2|'; while ( $line =~ m/([^|]+)\|([^|]+)\|/g ){ $file{$1}=$2; }
    And another note -- are all the keys unique? Because later ones will over-write earlier ones if they're not...
    --
    “Every bit of code is either naturally related to the problem at hand, or else it's an accidental side effect of the fact that you happened to solve the problem using a digital computer.”
    M-J D