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

Oh wise ones... I have the need to parse a file that lists variables. The file format is something like *rvd*daemonPort : 7500 or hostname*rvd*daemonPort : 7500 or could even extend to hostname*rvd*RTD*daemonPort : 7500. So the variables are scoped either globally or locally. Also, the variables will be unknown to me until I parse the file. So, Parsing the file is not difficult. The issue for me is putting the data into a usable array or hash.
while( <FILE> ) { @tmp = split(/\*/); SWITCH: { for ($i = 0; $i <= $#tmp; $i++) { if ($tmp[$i]) { # make sure the first value is the key. print "Setting key : $KEY\n", if ($Verbose); $KEY = "$tmp[$i]"; # populate the key with the other values # hostname*rvd*daemonPort : 7500 for ($i; $i <= $#tmp; $i++) { # reached the last var populate the va +lue if ( $tmp[$i] =~ /^(\w+)\s+\:\s+([A-Z. +0-9_\/])/ig) { $Vars{$KEY}{$tmp[$i - 1]}{$1} => $2; print "$tmp[$i]"; }else{ $Vars{$KEY}{$tmp[$i]}; } } last SWITCH; } } } } # while <file>
Obviously this is not going to work correctly. The real problem is getting a hash that looks like this $hash{rvd}{RTD}{daemonPort} => 7500; without knowing how deep I am going to go. Any ideas out there?

Replies are listed 'Best First'.
Re: Parse file to Hash of Hash etc.
by mrborisguy (Hermit) on May 18, 2005 at 18:08 UTC
    This code should make a string that looks like $hash{'hostname'}{'rvd'}{'RTD'}{'daemonPort'} = 7500, and then run an eval on it.
    my %hash; while( <> ) { my ( $front, $back ) = split /\s*:\s*/; my @keys = split /\*/, $front; eval( '$hash' . ( join '', map { "{'$_'}" } @keys ) . "=" . $back +); }
    Warning: Untested code.

    You could also do probably more easily do this with a recursive sub.
        Point taken. And a good read too. Thanks! I'll try to be more careful next time. Do you have a suggestion of the simplest way to do this safely?
        I think I understand what you are saying but the code from mrborisguy works great for me and I understand what it is doing, which for me is very important. I do not like to just cut and past code because in the end someone has to support it. I did try the data dumper but am unable to access the data on the return. ?? Probably since I don't know what I am doing :) maybe a plus one for for mrborisguy ?
      VERY cool One question.... What is recursive sub? I can not find it in my perl book.
        A recursive sub is when a sub calls itself in some form.
        The best example of this usually given is the mathematical function factorial (denoted by !). Are you familiar with it? 4! = 4*3*2*1. 7! = 7*6*5*4*3*2*1. In general, n! = n*(n-1)*(n-2)*...*2*1. But you could also say that n! = n*(n-1)!.

        so if you would make a sub called factorial, then it would be something like this:
        sub factorial { my $n = shift; return $n * &factorial( $n - 1 ); }
        but this obviously doesn't work, 'cause it will keep going and going, so you need a stopping point too.
        sub factorial { my $n = shift; if ( $n == 1 ) { return 1 } return $n * &factorial( $n - 1 ); }
        Try searching Google for recursive functions, recursive subs, recursion, etc.
      The untested code works just fine for me.