Solved

create hash out of a recursive string in perl

Posted on 2008-10-20
4
369 Views
Last Modified: 2012-05-05
I have the following string(s)and I want to generate a hash of hash from this one.

;&EVENT[__nmi_0](nmi, THREAD => 0, TRIGGER => &TRIGGER[__nmi_0.trigger](eom, LIP => 0x2020, SELF_CHECK => 'MUST_COMPLETE', THREAD => 0));

Hash %Event might look like this:

Event[nmi_0][event] = nmi
Event[nmi_0][Thread] =0
Event[nmi_0][Trigger] = __nmi_0.trigger
Event[nmi_0][__nmi_0.trigger][trigger] = eom
Event[nmi_0][__nmi_0.trigger][LIP] = 0x2020
Event[nmi_0][__nmi_0.trigger][SELF_CHECK] = 'MUST_COMPLETE'
Event[nmi_0][__nmi_0.trigger][THREAD] = 0


Below is an example of recursive strings.

;&EVENT[__psmi_1](psmi, THREAD => 0, TRIGGER => &TRIGGER[__retire_1](retire, LIP => 0x203f, TRIGGER => &EVENT[__smi_1](smi, THREAD => 1, TRIGGER => &TRIGGER[__eom_1](eom, LIP => 0x203f, THREAD => 0))));

Event[psmi_0][event] = psmi
Event[nmi_0][Thread] =0
Event[nmi_0][Trigger] = __retire_0.trigger
Event[nmi_0][__retire_0.trigger][trigger] = retire
Event[nmi_0][__retire_0.trigger][LIP] = 0x203f
Event[nmi_0][__nmi_0.trigger][trigger] = smi_1
Event[nmi_0][__nmi_0.trigger][smi_1][event] = smi
Event[nmi_0][__nmi_0.trigger][smi_1][Thread] = 0
Event[nmi_0][__nmi_0.trigger][smi_1][Trigger] = eom_1
Event[nmi_0][__nmi_0.trigger][smi_1][eom_1][event] = eom
Event[nmi_0][__nmi_0.trigger][smi_1][eom_1][Thread] = 0
Event[nmi_0][__nmi_0.trigger][smi_1][eom_1][LIP] = 0x203f


Can someone show me how to do hash like this? The string can have these events and triggers nested any number of times my hash has to build accordingly.

Thanks
0
Comment
Question by:Anu2117
  • 2
4 Comments
 

Author Comment

by:Anu2117
ID: 22761307
Event[psmi_0][event] = psmi
Event[psmi_0][Thread] =0
Event[psmi_0][Trigger] = __retire_0.trigger
Event[psmi_0][__retire_0.trigger][trigger] = retire
Event[psmi_0][__retire_0.trigger][LIP] = 0x203f
Event[psmi_0][__retire_0.trigger][trigger] = smi_1
Event[psmi_0][__retire_0.trigger][smi_1][event] = smi
Event[psmi_0][__retire_0.trigger][smi_1][Thread] = 0
Event[psmi_0][__retire_0.trigger][smi_1][Trigger] = eom_1
Event[psmi_0][__retire_0.trigger][smi_1][eom_1][event] = eom
Event[psmi_0][__retire_0.trigger][smi_1][eom_1][Thread] = 0
Event[psmi_0][__retire_0.trigger][smi_1][eom_1][LIP] = 0x203f

 
I made a mistake in my example hash, here is the correct hash interpretation for the string. This the 2nd example in my question above.
 
 
0
 
LVL 39

Accepted Solution

by:
Adam314 earned 500 total points
ID: 22761803
Your expected data doesn't seem consistent with your input string... but accounting for possible typos
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
 
my @str = (";&EVENT[__nmi_0](nmi, THREAD => 0, TRIGGER => &TRIGGER[__nmi_0.trigger](eom, LIP => 0x2020, SELF_CHECK => 'MUST_COMPLETE', THREAD => 0));",
           ";&EVENT[__psmi_1](psmi, THREAD => 0, TRIGGER => &TRIGGER[__retire_1](retire, LIP => 0x203f, TRIGGER => &EVENT[__smi_1](smi, THREAD => 1, TRIGGER => &TRIGGER[__eom_1](eom, LIP => 0x203f, THREAD => 0))));");
 
my %Event;
my %Pieces;
foreach (@str) {
	%Pieces = ();
	my $Cnt;
	
	1 while s/\&(\w+)\[__([^\]]+)\]\((\w+),\s+([^\(\)]+)\)/print "String=$_\n";$Cnt++;$Pieces{$Cnt}=MakeHash($1,$2,$3,$4);"$2:SubHash{$Cnt}"/ge;
	for my $piece (sort {$b <=> $a} keys %Pieces) {
		while(my ($k, $v) = each %{$Pieces{$piece}}) {
			if($v =~ /^(.*):SubHash{(\d+)}$/) {
				$Pieces{$piece}->{$k}=$1;
				$Pieces{$piece}->{$1}=$Pieces{$2};
			}
		}
	}
	if(/^;(.*):SubHash{(\d+)};$/) {
		$Event{$1}=$Pieces{$2};
	}
}
print Dumper(\%Event);
sub MakeHash {
	print "MakeHash(" . join("; ", @_) . ")\n";
	return {lc($_[0])=> $_[2], split(/[,=>\s]+/, $_[3])};
}

Open in new window

0
 

Author Closing Comment

by:Anu2117
ID: 31507961
Adam,

    The ultimate use of this hash is to pass it as an argument to xml::simple::xmlout() so, I can get an xml output of this hash. But I am not getting that desired output right. This hash looks almost like an example hash in xmlout() help, but the xml is not like what is expected. I will file another ticket for this. If you get a chance, please take a look. Thanks a lot for the help.
0
 
LVL 84

Expert Comment

by:ozo
ID: 22762516
use Data::Dumper;
$_=q;&EVENT[__psmi_1](psmi, THREAD => 0, TRIGGER => &TRIGGER[__retire_1](retire, LIP => 0x203f, TRIGGER => &EVENT[__smi_1](smi, THREAD => 1, TRIGGER => &TRIGGER[__eom_1](eom, LIP => 0x203f, THREAD => 0))));;
$Event=mkhash("event","psmi_0 => $_");
sub mkhash{
    my($n,$h)=@_;
    my %h;
    (my $re=$h)=~s/((\()|(\))|[^()]+)/${[')','']}[!$3]\Q$1\E${['(','']}[!$2]/gs;  
    $re=join'|',map quotemeta,$h=~/$re/;
    while( $h=~/(?:(\w+)\s*=>\s*)?(?:&(\w+)\[(\w+)\]\(($re)\)|(\w+)|'([^'']*)')/g ){
my $x=$3?"$3.\L$2":$1||$n;
      $h{$x}=$2?mkhash("\L$2",$4):$5.$6;

    }
    return \%h;
}
print Dumper $Event;
0

Featured Post

Gigs: Get Your Project Delivered by an Expert

Select from freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely and get projects done right.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Extract multiple value with delimiters from a string 4 170
perl script 4 106
Check file date before getting folder path 1 72
Awk Question 2 127
Email validation in proper way is  very important validation required in any web pages. This code is self explainable except that Regular Expression which I used for pattern matching. I originally published as a thread on my website : http://www…
In the distant past (last year) I hacked together a little toy that would allow a couple of Manager types to query, preview, and extract data from a number of MongoDB instances, to their tool of choice: Excel (http://dilbert.com/strips/comic/2007-08…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

776 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question