помочь печатать хэш-ключей для необходимого формата
-
26-09-2019 - |
Вопрос
Мне нужна помощь в печати данных из хеша / хеша REF в STDOUT или файл с данными в определенном порядке.
У меня есть рутина Perl, которая использует хэш-ссылки, такие как:
#!/usr/local/bin/perl
use strict;
use warnings;
use File::Basename;
use Data::Dumper;
my %MyItems;
my $ARGV ="/var/logdir/server1.log";
my $mon = 'Aug';
my $day = '06';
my $year = '2010';
while (my $line = <>)
{
chomp $line;
if ($line =~ m/(.* $mon $day) \d{2}:\d{2}:\d{2} $year: ([^:]+):backup:/)
{
my $server = basename $ARGV, '.log';
my $BckupDate="$1 $year";
my $BckupSet =$2;
$MyItems{$server}{$BckupSet}->{'MyLogdate'} = $BckupDate;
$MyItems{$server}{$BckupSet}->{'MyDataset'} = $BckupSet;
$MyItems{$server}{$BckupSet}->{'MyHost'} = $server;
if ($line =~ m/(ERROR|backup-size|backup-time|backup-status)[:=](.+)/)
{
my $BckupKey=$1;
my $BckupVal=$2;
$MyItems{$server}{$BckupSet}->{$BckupKey} = $BckupVal;
}
}
}
foreach( values %MyItems ) {
print "MyHost=>$_->{MyHost};MyLogdate=>$_->{MyLogdate};MyDataset=>$_->{MyDataset};'backup-time'=>$_->{'backup-time'};'backup-status'=>$_->{'backup-status'}\n";
}
Вывод с использованием самосвалов:
$VAR1 = 'server1';
$VAR2 = {
'abc1.mil.mad' => {
'ERROR' => ' If you are sure is not running, please remove the file and restart ',
'MyLogdate' => 'Fri Aug 06 2010',
'MyHost' => 'server1',
'MyDataset' => 'abc1.mil.mad'
},
'abc2.cfl.mil.mad' => {
'backup-size' => '187.24 GB',
'MyLogdate' => 'Fri Aug 06 2010',
'MyHost' => 'server1',
'backup-status' => 'Backup succeeded',
'backup-time' => '01:54:27',
'MyDataset' => 'abc2.cfl.mil.mad'
},
'abc4.mad_lvm' => {
'backup-size' => '422.99 GB',
'MyLogdate' => 'Fri Aug 06 2010',
'MyHost' => 'server1',
'backup-status' => 'Backup succeeded',
'backup-time' => '04:48:50',
'MyDataset' => 'abc4.mad_lvm'
}
};
Выход отформатирован, что я хотел бы увидеть:
MyHost=>server1;MyLogdate=>Fri Aug 06 2010;MyDataset=>abc2.cfl.mil.mad;backup-time=>Fri Aug 06 2010;backup-status=>Backup succeeded
Просто добавленные (8/7/2010): пример файла журнала RAW я использую: (недавно добавлено, чтобы обеспечить лучшее представление журнала источника)
Fri Aug 06 00:00:05 2010: abc2.cfl.mil.mad:backup:INFO: backup-set=abc2.cfl.mil.mad
Fri Aug 06 00:00:05 2010: abc2.cfl.mil.mad:backup:INFO: backup-date=20100806000004
Fri Aug 06 00:48:54 2010: abc4.mad_lvm:backup:INFO: backup-size=422.99 GB
Fri Aug 06 00:48:54 2010: abc4.mad_lvm:backup:INFO: PHASE END: Calculating backup size & checksums
Fri Aug 06 00:48:54 2010: abc4.mad_lvm:backup:INFO: backup-time=04:48:50
Fri Aug 06 00:48:54 2010: abc4.mad_lvm:backup:INFO: backup-status=Backup succeeded
Fri Aug 06 00:48:54 2010: abc4.mad_lvm:backup:INFO: Backup succeeded
Решение 4
Спасибо всем за качку в их помощи ... Это работает для меня.
for my $Server(keys%MyItems){
for my $BckupSet(keys%{$MyItems{$Server}}){
for(sort keys%{$MyItems{$Server}{$BckupSet}}){
print$_,'=>',$MyItems{$Server}{$BckupSet}{$_},';';
}
print"\n";
}
}
Другие советы
Я провел некоторое время, глядя на свой код, и я думаю, что у меня это выяснилось.
Причина, по которой это было трудно ответить, состоит в том, что вы непреднамеренно посадили красную сельдь - вывод самосвал данных.
Обратите внимание, как это показывает $VAR1 = 'server1';
а потом $VAR2 = { blah };
.
Вы называли самосвалом, как так: print Dumper %MyItems;
Проблема в том, что DUMPER хочет, чтобы выбросить список значений, поскольку списки Perl Platts, сложные структуры должны быть переданы посредством ссылки. Итак, вам нужно назвать самоуверенностью так:
print Dumper \%MyItems;
Это показывает всю структуру.
Когда вы назвали Дампер ранее, вы непреднамеренно выделили один слой своей структуры данных. Предлагаемые решения и ваш собственный код работают на этой раздетенной структуре.
Здесь я прикрепил к некоторым коде для обработки дополнительного слоя вложенности (и сделал его Perl 5,8 совместимым):
for my $server_items ( values %MyItems ) {
for my $record ( values %$server_items ) {
print join ';', map {
# Replace non-existant values with 'undef'
my $val = exists $record->{$_} ? $record->{$_} : 'undef';
"'$_'=>$val" # <-- this is what we print for each field
} qw( MyHost MyLogdate MyDataset backup-time backup-status );
print "\n";
}
}
Похоже, у вас есть много вопросов и мне нужна помощь, чтобы получить голову вокруг ряда концепций. Предлагаю, что вы публикуете запрос на Perlmonks в поисках мудрости Perl за помощью для улучшения вашего кода. Так отлично подходит для сосредоточенного вопроса, но вечера более поддается переработке кода.
** Оригинальный ответ: **
Чтобы обойти какие-либо проблемы с анализами, которые я не могу реплицироваться, я просто установил %MyItems
на вывод дампера, который вы предоставили.
Ваши предупреждения, которые вы упоминаете выше, связаны со всеми сложными цитирующими и повторяющимися кодировкой, которые у вас есть в своем оттенке. Я заменил свое заявление на печати с помощью map
упростить код.
Святое дерьмо, большое соединение карты BLAH не проще, вы можете думать. Но действительно, проще, потому что каждая отдельная единица выражения меньше. Что легче понимать и получить право? Что легче изменять и поддерживать в правильном и последовательном усадении?
print "'foo'=>$_->{foo};'bar'=>$_->{bar};boo'=>$_->{boo};'far'=>$_->{far}\n";
или
say join ';', map {
"'$_'=>$item->{$_}"
} qw( foo bar boo far );
Здесь вы можете добавить, удалить или переставить свой вывод просто, изменив список аргументов, переданных map
. Отказ С другим стилем у вас есть куча копирования / вставки.
На карте, которую я использую ниже, немного сложнее, в том, что она проверяет, определяется ли данный ключ перед печатью значения, и назначьте значение по умолчанию, если нет.
#!perl
use strict;
use warnings;
use feature 'say';
my %MyItems = (
'abc1.mil.mad' => {
'ERROR' => ' If you are sure is not running, please remove the file and restart ',
'MyLogdate' => 'Fri Aug 06 2010',
'MyHost' => 'server1',
'MyDataset' => 'abc1.mil.mad'
},
'abc2.cfl.mil.mad' => {
'backup-size' => '187.24 GB',
'MyLogdate' => 'Fri Aug 06 2010',
'MyHost' => 'server1',
'backup-status' => 'Backup succeeded',
'backup-time' => '01:54:27',
'MyDataset' => 'abc2.cfl.mil.mad'
},
'abc3.mil.mad' => {
'backup-size' => '46.07 GB',
'MyLogdate' => 'Fri Aug 06 2010',
'MyHost' => 'server1',
'backup-status' => 'Backup succeeded',
'backup-time' => '00:41:06',
'MyDataset' => 'abc3.mil.mad'
},
'abc4.mad_lvm' => {
'backup-size' => '422.99 GB',
'MyLogdate' => 'Fri Aug 06 2010',
'MyHost' => 'server1',
'backup-status' => 'Backup succeeded',
'backup-time' => '04:48:50',
'MyDataset' => 'abc4.mad_lvm'
}
);
for my $record ( values %MyItems ) {
say join ';', map {
my $val = $record->{$_} // 'undef'; # defined-or requires perl 5.10 or newer.
"'$_'=>$val" # <-- this is what we print for each field
} qw( MyHost MyLogdate MyDataset backup-time backup-status );
}
Не проверено, но он должен работать в теории. Это будет распечатать выводную строку для каждого из ключей для основных MyiTems Hash. Если вы хотите все это на одной строке, вы можете просто бросить n или добавить другой разделитель.
foreach( values %MyItems ) {
print "MyServer=>$_->{MyServer};MyLogdate=>$_->{MyLogdate};MyDataset=>$_->{MyDataset};backup-time=>$_->{backup-time};backup-status=>$_->{backup-status}\n";
}
Не отвечая на вопрос, который вы спросили, но это не кажется мне разумным.
Вы хотите, чтобы массив хэшей не хэш хэшей.
Хэшисты не заказываются, если вы хотите, чтобы они заказали, а затем используйте массив.