create hash out of a recursive string in perl

Posted on 2008-10-20
Medium Priority
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.

Question by:Anu2117
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2

Author Comment

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.
LVL 39

Accepted Solution

Adam314 earned 2000 total points
ID: 22761803
Your expected data doesn't seem consistent with your input string... but accounting for possible typos
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+)}$/) {
	if(/^;(.*):SubHash{(\d+)};$/) {
print Dumper(\%Event);
sub MakeHash {
	print "MakeHash(" . join("; ", @_) . ")\n";
	return {lc($_[0])=> $_[2], split(/[,=>\s]+/, $_[3])};

Open in new window


Author Closing Comment

ID: 31507961

    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.
LVL 84

Expert Comment

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 %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;

    return \%h;
print Dumper $Event;

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

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

I have been pestered over the years to produce and distribute regular data extracts, and often the request have explicitly requested the data be emailed as an Excel attachement; specifically Excel, as it appears: CSV files confuse (no Red or Green h…
A year or so back I was asked to have a play with MongoDB; within half an hour I had downloaded (http://www.mongodb.org/downloads),  installed and started the daemon, and had a console window open. After an hour or two of playing at the command …
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…
Six Sigma Control Plans

777 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