#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
Вы указываете, что есть дополнительные данные — я только что попытался определить, как могут работать остальные ваши данные, так что это может быть неправильно.