Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

property file parsing

by mifflin (Curate)
on Feb 03, 2006 at 21:00 UTC ( [id://527816]=perlquestion: print w/replies, xml ) Need Help??

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

I have a properties file that is structured like the typical string=value where the string portion is formated like key1.key2...keyn

the problem is that I don't know the 'n' (how many key portions are in the string) and I'm looking for a way to be able to dynamincally handle it.

Here is a small sample of the properties file..

language_id.en_US=-1 language_id.es_US=-11 language_id.en_CA=-12 language_id.fr_CA=-13 langid.SPMEX=es_US langid.FRCAN=fr_CA altlang.US=SPMEX altlang.CA=FRCAN itemattr.newpart.seq=1 itemattr.newpart.name=New Part itemattr.newpart.image1.en_US=newitem_icon.gif itemattr.newpart.image1.es_US=newitem_icon_sp.gif itemattr.newpart.image1.en_CA=newitem_icon.gif itemattr.newpart.image1.fr_CA=newitem_icon_fr.gif itemattr.watersaver.seq=2 itemattr.watersaver.name=New Part itemattr.watersaver.image1.en_US=newitem_icon.gif itemattr.watersaver.image1.es_US=newitem_icon_sp.gif itemattr.watersaver.image1.en_CA=newitem_icon.gif itemattr.watersaver.image1.fr_CA=newitem_icon_fr.gif
Here is the relevant section of my code that parses this file...
my %properties; my $propfilename = $opt{p} ? $opt{p} : "$FindBin::Bin/${FindBin::Scrip +t}.properties"; print "reading properties from $propfilename\n" if $opt{v}; my $pfh = IO::File->new("<$propfilename") or die "unable to open prope +rties file $propfilename, $!"; while (my $propline = <$pfh>) { next if $propline =~ /^#/; print $propline if $opt{V}; chomp $propline; my ($key, $value) = split(/=/, $propline); my ($key1, $key2, $key3, $key4) = split(/\./, $key); if (defined $key4) { $properties{$key1}{$key2}{$key3}{$key4} = $value; } elsif (defined $key3) { $properties{$key1}{$key2}{$key3} = $value; } elsif (defined $key2) { $properties{$key1}{$key2} = $value; } elsif (defined $key1) { $properties{$key1} = $value; } } $pfh->close;
What I don't like is all the hard coding of handling n keys. As you can see I only hand up to four. Is there a better way to do this?

Replies are listed 'Best First'.
Re: property file parsing
by pKai (Priest) on Feb 03, 2006 at 21:56 UTC
    This works by recursively constructing branches of the tree top-down and works with arbitrary "deep" keys:
    use strict; use warnings; use Data::Dumper; my %properties; while (my $propline = <DATA>) { next if $propline =~ /^#/; chomp $propline; my ($key, $value) = split(/=/, $propline, 2); _insert(\%properties, $key, $value); } sub _insert { my ($root, $key, $value) = @_; my ($first, $rest) = split /\./, $key, 2; if (defined $rest) { $root->{$first} = {} unless ref($root->{$first}) eq 'HASH'; _insert($root->{$first}, $rest, $value); } else { $root->{$first} = $value; } } print Dumper(\%properties); __DATA__
      No need for recursion if a simple loop suffices:
      my ( $first, @subkeys ) = split /\./, $key; my $last = pop @subkeys; my $ref = $properties{$first} ||= {}; $ref = $ref->{$_} ||= {} for(@subkeys); $ref->{$last} = $value;

        Yeah, _insert is even tail recursive, so making a loop from it is no big deal. But, believe it or not, those recursive solutions just come more easily to me.

        BTW, your snippet fails to overwrite previously set to "True" scalar values. There is no case of this in the OP data sample. But this kind of anomaly is clobbered the same way by OP's script and mine.
        So you can even argue, that your algorithm crashing on such data is a feature :)

        perfect! thankyou.
Re: property file parsing
by coreolyn (Parson) on Feb 03, 2006 at 21:28 UTC

    Just on a quick look I have to say I'm confused by the format of your property file. Changing of its format would provide for much greater flexibility and available coding options. Is the property file form able to be changed?

      Nope, I'm stuck with it. I'm just trying to parse into a HoH's that works for me.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://527816]
Approved by Limbic~Region
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others goofing around in the Monastery: (6)
As of 2024-04-23 17:43 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found