Load file into a hash

B

Bill H

Is there a "perl" way of loading a file directly into a hash instead
of using something like this quick example:

open(FILE,"test.txt");
while(<FILE>)
{
$line = $_;
chop $line;
@dbf = split(/\t/,$line);
$MYHASH{$dbf[0]} = $dbf[1];
}
close(FILE);

where the text file contains entries like this:

NAME0\tsome value
NAME1\tanother value

etc... ?

Bill H
 
M

Mark Clements

Bill said:
Is there a "perl" way of loading a file directly into a hash instead
of using something like this quick example:

open(FILE,"test.txt");
while(<FILE>)
{
$line = $_;
chop $line;
@dbf = split(/\t/,$line);
$MYHASH{$dbf[0]} = $dbf[1];
}
close(FILE);

where the text file contains entries like this:

NAME0\tsome value
NAME1\tanother value

C:\TEMP>cat loadarray.pl
#!perl

use strict;
use warnings;

use Data::Dumper;

my $filename = shift;
open my $fh,"<",$filename or die $!;

my %hash = map { chomp; split /\t/ } <$fh>;

print Dumper(\%hash);

close $fh or die $!;

C:\TEMP>cat data.txt
UK London
France Paris
Italy Rome
USA Washington
Germany Berlin

C:\TEMP>loadarray.pl data.txt
$VAR1 = {
'France' => 'Paris',
'UK' => 'London',
'Italy' => 'Rome',
'Germany' => 'Berlin',
'USA' => 'Washington'
};

C:\TEMP>

Mark
 
B

Bill H

Bill said:
Is there a "perl" way of loading a file directly into a hash instead
of using something like this quick example:
open(FILE,"test.txt");
while(<FILE>)
{
$line = $_;
chop $line;
@dbf = split(/\t/,$line);
$MYHASH{$dbf[0]} = $dbf[1];
}
close(FILE);
where the text file contains entries like this:
NAME0\tsome value
NAME1\tanother value

C:\TEMP>cat loadarray.pl
#!perl

use strict;
use warnings;

use Data::Dumper;

my $filename = shift;
open my $fh,"<",$filename or die $!;

my %hash = map { chomp; split /\t/ } <$fh>;

print Dumper(\%hash);

close $fh or die $!;

C:\TEMP>cat data.txt
UK London
France Paris
Italy Rome
USA Washington
Germany Berlin

C:\TEMP>loadarray.pl data.txt
$VAR1 = {
'France' => 'Paris',
'UK' => 'London',
'Italy' => 'Rome',
'Germany' => 'Berlin',
'USA' => 'Washington'
};

C:\TEMP>

Mark- Hide quoted text -

- Show quoted text -

I like that Mark. You basically took everything I had in the while
loop and put it on one line. Nice and neat.

Bill H
 
B

Brian McCauley

my %hash = map { chomp; split /\t/ } <$fh>;

That works but is very fragile - one bad line can screw all your data
from then on.

I prefer (the canonical idiom)

my %hash = map { /(.*?)\t(.*)/ } <$fh>;

This will ignore lines with no "\t" in them. Do something vaguely
reasonable with lines containing more than one "\t". Oh, and it's
shorter too.
 
B

Brian McCauley

my %hash = map { /(.*?)\t(.*)/ } <$fh>;

Oh, and since we're slurping the file anyhow we can save a few lines
by using File::Slurp

use File::Slurp;
my %hash = map { /(.*?)\t(.*)/ } read_file('test.txt');
 
M

Martijn Lievaart

That works but is very fragile - one bad line can screw all your data
from then on.

I prefer (the canonical idiom)

my %hash = map { /(.*?)\t(.*)/ } <$fh>;

This will ignore lines with no "\t" in them. Do something vaguely
reasonable with lines containing more than one "\t". Oh, and it's
shorter too.

Doesn't that include the newline on any line in the second field?

M4
 
T

Tad McClellan

Martijn Lievaart said:
On Sat, 06 Oct 2007 14:06:18 +0000, Brian McCauley wrote:


Doesn't that include the newline on any line in the second field?


Which part of the regex can match those newlines?
 
T

Tad McClellan

Bill H said:
Is there a "perl" way of loading a file directly into a hash instead
of using something like this quick example:

open(FILE,"test.txt");


You should always, yes *always*, check the return value from open().

while(<FILE>)
{
$line = $_;


If you want it in $line, then put it there, rather than put it
somewhere else and then move it there:

chop $line;


You should use chomp() to remove newlines.


my %myhash = split /[\t\n]/, do{ local $/; <FILE>};
 
U

Uri Guttman

BM> Oh, and since we're slurping the file anyhow we can save a few lines
BM> by using File::Slurp

BM> use File::Slurp;
BM> my %hash = map { /(.*?)\t(.*)/ } read_file('test.txt');

i was going to chime in with slurp as well. :)

i have a better and faster idiom for slurping files into hashes
(untested for typos):

my %hash = read_file('test.txt') =~ /^([^\t]+)\t(.*)$/gm ;

and for most config type files slurping is fast since they are likely
smaller than even the OS's I/O block size which can be 64k or even
256k. there is no savings using perl's i/o system and reading many files
line by line. it is a great teaching technique but it is slower than
slurping in a whole file and parsing it in one regex call (as is
possible in many cases).

uri
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top