Анализ данных и подгонка под хэш не дают ожидаемого результата

#arrays #perl #hash

#массивы #perl #хэш

Вопрос:

У меня есть данные, которые необходимо проанализировать и распечатать на экране.

Вот данные и мой скрипт:

Входные данные:

 __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]
 

Скрипт:

 #!/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_antn";
    print "car_$i:", join('###', uniq @{$hash3{$sec_ant}}), "n";
}
 

Это мой текущий результат:

 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
 

Ожидаемый результат:

 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
 

Поскольку он должен искать Node значение без Car данных и выбирать соответствующие SecAnt данные. И на основе Node значения, соответствующие Sec Car данные (из hash2 ) должны быть выбраны с использованием resBy Node данных. Как я могу это сделать?

Комментарии:

1. Можете ли вы объяснить, как resBy: записи имеют отношение к результату?

2. @clamp В данном случае не имеет к этому никакого отношения. Он использовался в другом сценарии.

3. Итак, как нужно выбирать с помощью строки ключевого слова resBy. применить?

4. @clamp ваш вопрос имеет смысл. Я исправил это.

5. Будет ли ваш фактический набор данных включать другие узлы? Если да, ссылается ли «На основе значения узла » на значение Node=S01 или оно ссылается на данные, присвоенные $node в вашем примере кода?

Ответ №1:

Могу ли я предложить использовать $/ в качестве разделителя записей? Это упростит задачу. Я думаю, что вы слишком усложняете ситуацию своими составными условными обозначениями. Как насчет:

 #!/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_antn";
    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]
 

Мы используем $/ для установки режима «абзац», поэтому каждая итерация цикла while разделяется пустой строкой.

Мы извлекаем из каждой записи сведения об «узле», а затем сопоставляем Ref или resBy , чтобы решить, что делать с остальной частью узла — обрабатываем Ref узел как родительский (и устанавливаем $current каждый раз, когда мы сталкиваемся с ним) и a resBy как дочерний, чтобы поместить значение в $current ветвь хэша.

Это приводит к запрошенному результату:

 $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
 

Вы указываете, что есть дополнительные данные — я только что попытался определить, как могут работать остальные ваши данные, так что это может быть неправильно.