Parse data and fit in Hash gives not expected result

Viewed 90

I have data which need to be parsed and print on the screen.

Here is the data and my script:

Input Data:

__DATA__
Node : Network=Europe,Network=Ireland,Node=S01,Sec=1
Ref : [Network=Europe,Network=Ireland,Node=S01,SecAnt=1]

Node : Network=Europe,Network=Ireland,Node=S01,Sec=1,Car=1
resBy : [Network=Europe,Network=Ireland,Node=S01,Cell=1]

Node : Network=Europe,Network=Ireland,Node=S01,Sec=1,Car=2
resBy : [Network=Europe,Network=Ireland,Node=S01,Cell=1]

Script:

#!/usr/bin/perl

use strict; use warnings;
use Data::Dumper;

use List::Util qw /uniq/;

my ($node, $item, %hash1, %hash2, %hash3);

while (my $line = <DATA>){
    chomp $line;

    if ($line =~ m/^\s*Node :\s*(.*?)(,Car=\d+)?\s*$/) { 
        $node = $1;
    } elsif ($line =~ m/^\s*Ref :\s*\[*(.*?)\]*\s*$/) { 
        $hash1{$node} = [ split /, /,$1 ] ; 
        ($node, $item) = "";
    } elsif ($line =~ m/^\s*resBy :\s*\[*(.*?)\]*\s*$/) {
        $hash2{$node} = [ split /, /,$1 ]; 
        ($node, $item) = "";
    }
}

foreach my $sec (keys %hash1){
    foreach my $ant (@{$hash1{$sec}}) {
        push @{$hash3{$ant}}, $sec;
    }
}
print "Hash3:\n". Dumper(\%hash3); 

my $i = 0;
foreach my $sec_ant (sort keys %hash3){
    ++$i;
    print "sec_ant_$i:$sec_ant\n";
    print "car_$i:", join('###', uniq @{$hash3{$sec_ant}}), "\n";
}

This is my current output:

Hash3:
$VAR1 = {
          'Network=Europe,Network=Ireland,Node=S01,SecAnt=1' => [ 
                          'Network=Europe,Network=Ireland,Node=S01,Sec=1'
          ]
};
sec_ant_1:Network=Europe,Network=Ireland,Node=S01,SecAnt=1
car_1:Network=Europe,Network=Ireland,Node=S01,Sec=1

Expected result:

Hash3:
$VAR1 = {
          'Network=Europe,Network=Ireland,Node=S01,SecAnt=1' => [
                 'Network=Europe,Network=Ireland,Node=S01,Sec=1,Car=1', 
                 'Network=Europe,Network=Ireland,Node=S01,Sec=1,Car=2',
          ]
};
sec_ant_1:Network=Europe,Network=Ireland,Node=S01,SecAnt=1
car_1:Network=Europe,Network=Ireland,Node=S01,Sec=1,Car=1###Network=Europe,Network=Ireland,Node=S01,Sec=1,Car=2

Since it should look for a Node value without Car data, and pick the respective SecAnt data. And Based on the Node value the corresponding Sec+Car data(from hash2) needed to be picked by the use of resBy's Node data. How can I do that?

1 Answers

Can I suggest making use of $/ as a record separator? It'll make this task easier. I think you're overcomplicating things with your compound conditionals. How about:

#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;
use List::Util qw /uniq/;

my %results;

#current 'parent' node
my $current;

#parse input as paragraphs - blank line delimited. 
$/ = '';
#iterate the data - we don't bother setting `$line` because it's not necessary
#as all data is extracted via pattern matches against implicit $_      
while (<DATA>) {
    #if we're a Ref stanza, set the current node. 
    if (m/Ref : (.*)/) {
        $current = $1;
    }
    #if we're a resBy stanza, insert the node into the parent
    #using push, so we don't overwrite. 
    if (m/resBy/) {
        m/Node : (.*)/;
        push( @{ $results{$current} }, $1 );
    }
}

print Dumper \%results;


my $count;
foreach my $sec_ant ( sort keys %results ) {
    ++$count;
    print "sec_ant_${count}:$sec_ant\n";
    print "car_${count}:", join( '###', uniq @{ $results{$sec_ant} } ), "\n";
}

__DATA__
Node : Network=Europe,Network=Ireland,Node=S01,Sec=1
Ref : [Network=Europe,Network=Ireland,Node=S01,SecAnt=1]

Node : Network=Europe,Network=Ireland,Node=S01,Sec=1,Car=1
resBy : [Network=Europe,Network=Ireland,Node=S01,Cell=1]

Node : Network=Europe,Network=Ireland,Node=S01,Sec=1,Car=2
resBy : [Network=Europe,Network=Ireland,Node=S01,Cell=1]

We're using $/ to set 'paragraph' mode, so each iteration of the while loop is blank line delimited.

We extract from each record the 'Node' details, and then match Ref or resBy to decide what to do with the rest of the node - treating a Ref node as a parent (and setting $current each time we encounter one) and a resBy as a child, to push the value into the $current branch of the hash.

This produces the output requested:

$VAR1 = {
          '[Network=Europe,Network=Ireland,Node=S01,SecAnt=1]' => [
               'Network=Europe,Network=Ireland,Node=S01,Sec=1,Car=1',
               'Network=Europe,Network=Ireland,Node=S01,Sec=1,Car=2'
                                                                  ]
        };
sec_ant_1:[Network=Europe,Network=Ireland,Node=S01,SecAnt=1]
car_1:Network=Europe,Network=Ireland,Node=S01,Sec=1,Car=1###Network=Europe,Network=Ireland,Node=S01,Sec=1,Car=2

You indicate there's additional data - I've just tried to infer what the rest of your data might work like, so this could be wrong.

Related