Hi Monks,
I had posted the query earlier and was asked to do some ground work. Below is the code I have tried and now looking forward to your suggestions
Here is the script...
#! /usr/bin/perl use strict; use Data::Dumper; my ( %linked_dsc, $main_var, @actions ); my $maincnt = 0; my $found = 0; my ($t1, $t2); my $contitent_hash = { }; open (FILE, "./Data.txt") or die "Can't find file"; while (<FILE>) { # From start of 1st 'Main' to start of 2nd 'Main', read the lines and # store in appropriate variables # $contitent_hash has abbreviation as key and full name as value # @actions has search patterns to look for in the next pass # for example: 'NA' => 'North America' is in the hash variable and # 'Name = NA' is in the array if ( /^Main$/ ) { $maincnt++; } if ( $maincnt == 1 ) { if ( /^Main/../^End/) { if ( /^\s*(.*)\s=\s(.*)/ ) { if ( $1 eq "Name") { $main_var = $2; #$linked_dsc{ $main_var } = undef; } } } elsif ( /^Sub/../^End/) { if ( /^\s*(.*)\s=\s(.*)/ ) { if ( $1 eq "Action") { ($t1, $t2) = split ( /: /, $2 ); push @actions, ('Name = '. $t2 ); $contitent_hash->{ $t2 } = undef; } elsif ( $1 eq "Text") { $contitent_hash->{ $t2 } = $2; } } } } last if ( $maincnt > 1); } # Self checking... print "---------------------\n"; print "@actions\n"; print "---------------------\n"; foreach my $key ( keys %{ $contitent_hash } ) { print "$key = $contitent_hash->{ $key }\n"; #$linked_dsc{ $main_var }{ $contitent_hash->{ $key } } = undef; } print "---------------------\n"; # End of self check foreach ( @actions ) { print "SEARCH STRING: $_\n"; my (undef, $link_word) = split / = /; my ($ret_dsc, $ret_arr ) = process_next( $_ ); foreach my $key1 ( keys %{ $ret_dsc } ) { # Checking... print "$key1 = $ret_dsc->{ $key1 }\n"; $linked_dsc{ $main_var }{ $contitent_hash->{ $link_word } }{ $ +ret_dsc->{ $key1 } } = undef; } #Checking... #print Dumper ( $ret_dsc ); #print Dumper ( $ret_arr ); } print Dumper ( \%linked_dsc ); # Subroutine to search for the searchstring in the file, start reading + # the subsequent lines and store in appropriate variables until the # next 'Main' is encountered. sub process_next { my $searchstr = shift; my $new_href= { }; my ( @new_actions, $left_val, $right_val); seek ( FILE, 0, 0 ); $found = 0; while ( <FILE> ) { if ( ! $found ) { if ( ! /$searchstr/ ) { next; } else { $found = 1; } } if ( $found ) { if ( /^Sub/../^End/) { if ( /^\s*(.*)\s=\s(.*)/ ) { if ( $1 eq "Action") { ($left_val, $right_val ) = split ( /: /, $2 ); if ( defined $right_val ) { $new_href->{ $right_val } = undef; push @new_actions, ('Name = '. $right_val +); }; #else { print "Not defined\n" }; } elsif ( $1 eq "Text") { if (defined $right_val) { $new_href->{ $right_val } = $2; } else { $new_href->{ $2 } = $2 }; } } } last if ( /Main/ ); } } # Checking... # print "new actions : @new_actions\n"; return $new_href, \@new_actions; }
I am sure it is not great, but I have given a try....
I am able to go to 2 levels but confused as to how to make this more generic. Two issues I have are:-
1)The way I build the data structure doesn't seem to be right, although it produces the result (as it is not generic)
$linked_dsc{ $main_var }{ $contitent_hash->{ $link_word } }{ $ret_dsc->{ $key1 } } = undef;
The data file is not limited to what is shown and hence, this approach becomes clumpsy if the hash tree gets deeper
2) I have to call the subroutine again for each element in the array @new_actions. I don't how to proceed with that.
Please help
Here is the data file...
Line nos added for reference.. 1 Main 2 Name = Countries 3 End 4 5 Sub 6 Action = Find: NA 7 Text = North America 8 End 9 10 Sub 11 Action = Find: EU 12 Text = Europe 13 End 14 15 Main 16 Name = NA 17 End 18 19 Sub 20 Action = Find: US 21 Text = United States 22 End 23 24 Sub 25 Action = Find: CA 26 Text = Canada 27 End 28 29 Sub 30 Action = Find: MX 31 Text = Mexico 32 End 33 34 Main 35 Name = US 36 End 37 38 Sub 39 Action = 40 Text = Boston 41 End 42 43 Sub 44 Action = 45 Text = Atlanta 46 End 47 48 Main 49 Name = EU 50 End 51 52 Sub 53 Action = 54 Text = France 55 End 56 57 Sub 58 Action = 59 Text = Italy 60 End
Output looks as follows:-
--------------------- Name = NA Name = EU --------------------- NA = North America EU = Europe --------------------- SEARCH STRING: Name = NA US = United States CA = Canada MX = Mexico SEARCH STRING: Name = EU Italy = Italy France = France $VAR1 = { 'World' => { 'Europe' => { 'France' => undef, 'Italy' => undef }, 'North America' => { 'Mexico' => undef, 'United States' => undef, 'Canada' => undef } } };
In reply to Building hash tree from data file -contd by Anonymous Monk
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |