Mark.Allan has asked for the wisdom of the Perl Monks concerning the following question:

I have the following text file of configuration details. This is a inhertitance configured file

.
######## PARENT CONFIG ############## DEPLOY : SWG_Lower HOLDS SWG_Depot EQUALS:= total_dist: completion= SUCCESS total_finish: completion= SUCESS total_cancel:completion=SUCCESS DEPLOYED DEPLOY: LOADED_Lower HOLDS SWG_Depot EQUALS = total_finish: completion= SUCCES total_cancel: completion=SUCCESS DEPLOYED DEPLOY: CONFIG_Lower HOLDS SWG_Depot EQUALS = total_cancel: completion=SUCCESS DEPLOYED ######### INHERITED CHILD CONFIG ############### DEPLOY first_distribution HOLDS LOADED_Lower DEPLOYED DEPLOY: second_distribution HOLDS CONFIG_Lower ; DEPLOYED DEPLOY : third_distribution HOLDS LOADED_Lower; DEPLOYED DEPLOY : forth_distribution HOLDS SWG_Lower ; DEPLOYED

I need to match a string variable with a hash key. The fields first_distribution , second_distribution are keys stored in a hash called results{keyid} and I match them in this file. What I am doing is follows. I first match a key in the file, then I need to collate the attributes associated with each PARENT ID, attributes for example are total_dist:, total_cancel

while( $line = <FH>) { next unless $line =~ m<\s+(\S+)\sHOLDS\s(.+)>x; $key = $1; #Obtains first_distribution, etc if ($line =~ /(\S+_Lower)\sHOLDS\s\S+/i) { $base_type = $1; #obtains parent config ID (eg SWG_Lo +wer ) while ($line =~ m<\s(\S+):\s(completion).+>gx) # obta +ining attributes { push(@{$base{$base_type}}, $1);}} # push each att +ribute associated with parent ID into an hash of arrays # eg A dump from the hash looks like this whi +ch is correct SWG_Lower:: total_dist total_finish total_cancel LOADE +D_Lower:: total_finish, total_cancel : CONFIG +_Lower: total_cancel next unless exists $results{$key}; # I do this incase ther +e are distribution ids in the file which are not in my hash

Now where Im struggling is as follows.. The child IDs need to inherit the PARENT attributes if distributions holds one of the PARENT IDS, example

eg. The child ID second_distribution HOLDS CONFIG_Lower which matches CONFIG_Lower in the base{$base_type) hash key therefore needs to inherit the attribute from CONFIG_lower and push into an already pre-defined hash of hashes value $results{Łkey}{$dist_attr}

DEPLOY: second_distribution HOLDS CONFIG_Lower ; DEPLOYED

Therefore the attribute " total_cancel" needs to associated with second_distribution, and if it is, update an hash key called $results{Łkey}{$dist_attr} with the value total_cancel, an example for forth_distribution would be

DEPLOY : forth_distribution HOLDS SWG_Lower ; DEPLOYED

The attributes total_dist, total_cancel and total_finish (attributes of SWG_Lower) would need to be joined with # and the following value total_dist#total_cancel#total_finish pushed into $results{Łkey}{$dist_attr} hash value. Does this make sense? it was hard for me to explain never mind write

Replies are listed 'Best First'.
Re: Matching String Value with Hash Key
by kcott (Archbishop) on Sep 28, 2013 at 09:32 UTC

    G'day Mark.Allan,

    "Does this make sense? it was hard for me to explain never mind write"

    To be honest, I'm not entirely sure: hopefully, I got the gist of it. Here's some issues I found:

    • There's some code that just won't work, e.g. a number of regexes have \s but the data you're trying to match (as shown) has 0, 1 or 2 spaces.
    • You have a complicated way of determining parent and child config: was there a reason you didn't just look for PARENT CONFIG and CHILD CONFIG.
    • In your description you have: e.g. "a hash called results{keyid}" — that's not the name of a hash, the key keyid appears nowhere in the code, there's a $results{$key} in the code but %results is neither declared nor populated.
    • Three times in your description, you have: "$results{Łkey}{$dist_attr}" — obviously, your '$' key works; whatever sigil you intended when you entered 'Ł' is almost certainly wrong; there's nothing like that in the code you posted so I can't even guess what was intended.
    • In your code, you have a regex where you're matching and capturing the literal text 'completion' — you may have intended to capture something else; regardless, the captured data (which would have been $2) is not used anywhere.
    • There maybe others.

    Here's a script that captures the data you want. I'll leave you to format the output.

    #!/usr/bin/env perl use strict; use warnings; use autodie; my $config_file = 'pm_1056046_parse_config.txt'; my $gen = 'parent'; my %cfg; { local $/ = "DEPLOYED\n"; open my $config_fh, '<', $config_file; while (<$config_fh>) { $gen = 'child' if /CHILD CONFIG/; /(\w+)\s+HOLDS\s+(\w+)/; $cfg{$gen}{$1}{holds} = $2 if $gen eq 'child'; push @{$cfg{parent}{$1}{equals}} => /(total_\w+)/g if $gen eq +'parent'; } close $config_fh; } for (keys %{$cfg{child}}) { print "$_ : @{$cfg{parent}{$cfg{child}{$_}{holds}}{equals}}\n"; }

    Output:

    $ pm_1056046_parse_config.pl first_distribution : total_finish total_cancel second_distribution : total_cancel third_distribution : total_finish total_cancel forth_distribution : total_dist total_finish total_cancel

    -- Ken

      Ken

      Thanks for your input, I'll pick up on this tomorrow but one thing I failed to highlight is that ###parent config#### and #####child config##### don't actually exist in the file, it's was merely me defining the structure which I forgot to mention

      The exact file looks likes this

      DEPLOY : SWG_Lower HOLDS SWG_Depot EQUALS:= total_dist: completion= SUCCESS total_finish: completion= SUCCESS total_cancel:completion=SUCCESS DEPLOYED DEPLOY: LOADED_Lower HOLDS SWG_Depot EQUALS:= total_finish: completion= SUCCESS total_cancel: completion=SUCCESS DEPLOYED DEPLOY: CONFIG_Lower HOLDS SWG_Depot EQUALS:= total_cancel: completion=SUCCESS DEPLOYED DEPLOY first_distribution HOLDS LOADED_Lower DEPLOYED DEPLOY: second_distribution HOLDS CONFIG_Lower ; DEPLOYED DEPLOY : third_distribution HOLDS LOADED_Lower; DEPLOYED DEPLOY : forth_distribution HOLDS SWG_Lower ; DEPLOYED
        "... one thing I failed to highlight is that ###parent config#### and #####child config##### don't actually exist in the file, it's was merely me defining the structure which I forgot to mention"

        You actually wrote:

        "I have the following text file of configuration details."

        It's important to pay attention to details. I can only provide advice on dealing with the input you describe: I can't guess that some of what you provide is correct and other parts are not. Furthermore, the computer can only deal with the input (as you describe it) in your code; for instance, any attempt to match either version of the input with the pattern '#parent config#' would fail.

        You may think I'm being pedantic; however, if you look back to the issues I originally raised, you'll see that all six of them are related to a lack of attention to detail.

        For your latest version of your input, you can modify my code by changing

        $gen = 'child' if /CHILD CONFIG/;

        to

        $gen = 'child' unless /EQUALS/;

        and get the same output values.

        -- Ken

Re: Matching String Value with Hash Key
by marinersk (Priest) on Sep 27, 2013 at 23:37 UTC
    Okay, so as you indicate, this is complicated and difficult to explain -- worse to have to type it out. I empathize -- truly.

    So naturally the first thing I need to do is get into your headspace -- easiest way is to take your data and code and run it to get a feel for what it is trying to do.

    So I wrapped your code in a subroutine (mainly to isolate my code from yours) and called it.

    Either you didn't give me everything, or something is seriously wrong with your code:

    #!/usr/bin/perl -w use strict; foreach my $configFilename (@ARGV) { if (open FH, '<', $configFilename) { &processConfigFile(); } } exit; __END__ C:\Steve\Dev\PerlMonks\P-2013-09-27@1720-Config-Parent>perl configPare +nt.pl Bareword "LOADED_Lower::" refers to nonexistent package at configParen +t.pl line 32. Global symbol "$line" requires explicit package name at configParent.p +l line 19. Global symbol "$line" requires explicit package name at configParent.p +l line 21. Global symbol "$key" requires explicit package name at configParent.pl + line 22. Global symbol "$line" requires explicit package name at configParent.p +l line 24. Global symbol "$base_type" requires explicit package name at configPar +ent.pl line 26. Global symbol "$line" requires explicit package name at configParent.p +l line 28. Global symbol "%base" requires explicit package name at configParent.p +l line 30. Global symbol "$base_type" requires explicit package name at configPar +ent.pl line 30. syntax error at configParent.pl line 32, near "LOADED_Lower:: total_fi +nish" Global symbol "%results" requires explicit package name at configParen +t.pl line 35. Global symbol "$key" requires explicit package name at configParent.pl + line 35. Missing right curly or square bracket at configParent.pl line 39, at e +nd of line configParent.pl has too many errors.

    So we'll need to get past this before I'm going to be of much use to you.

    The full code I used is here so we can compare apples to apples as we work through this:

Re: Matching String Value with Hash Key (ddumper)
by Anonymous Monk on Sep 27, 2013 at 22:32 UTC

    Now where Im struggling is as follows.. The child IDs need to inherit the PARENT attributes if distributions holds one of the PARENT IDS, example

    Great, ddumperBasic debugging checklist up a \%parent and \%child and I'll help you inherit-into-child attributes from parent:)

    Oh, you say you don't have a %parent and a %child? First thing I would do I create those :)

    Would you like to hear more?

      Hi thanks for input , the parent config is dumped out in %base hash, the distribution IDs are matched against $key ?

        Hi thanks for input , the parent config is dumped out in %base hash, the distribution IDs are matched against $key ?

        I'm sorry, what?