create hash out of a recursive string in perl

Posted on 2008-10-20
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
  • 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 500 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

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Suggested Solutions

A year or so back I was asked to have a play with MongoDB; within half an hour I had downloaded (,  installed and started the daemon, and had a console window open. After an hour or two of playing at the command …
There are many situations when we need to display the data in sorted order. For example: Student details by name or by rank or by total marks etc. If you are working on data driven based projects then you will use sorting techniques very frequently.…
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…
This video discusses moving either the default database or any database to a new volume.

760 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

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now