помочь распечатать ключи хеша в нужный формат - PullRequest
0 голосов
/ 07 августа 2010

Мне нужна помощь в распечатке данных из ссылки на хеш / хэш в 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

Только что добавлено (7 августа 2010 г.): Пример файла необработанного журналаЯ использую: (недавно добавлено для лучшего представления исходного журнала)

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 ]

1 голос
/ 07 августа 2010

Я потратил некоторое время на просмотр вашего кода и думаю, что понял его.

Причина, по которой трудно было ответить, заключается в том, что вы непреднамеренно посадили красную сельдь - дампер данныхoutput.

Обратите внимание, как он показывает $VAR1 = 'server1';, а затем $VAR2 = { blah };.

Вы назвали Dumper следующим образом: print Dumper %MyItems;

Проблема в том, что Dumper хочет списокзначений для дампа, поскольку Perl выравнивает списки, сложные структуры должны передаваться по ссылке.Итак, вам нужно вызвать Dumper следующим образом:

print Dumper \%MyItems;

Это показывает всю структуру.

Когда вы вызывали dumper ранее, вы случайно удалили один слой вашей структуры данных.Предлагаемые решения и ваш собственный код работают с этой раздетой структурой.

Здесь я привел некоторый код для обработки дополнительного уровня вложенности (и сделал его совместимым с 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 в Seekers of Perl Wisdom для помощи в улучшении вашего кода.SO отлично подходит для сфокусированного вопроса, но PM более поддается переработке кода.

** Оригинальный ответ: **

Чтобы обойти любые проблемы с синтаксическим анализом, которые я не могу воспроизвести, я простоустановите %MyItems на вывод Dumper, который вы предоставили.

Ваши предупреждения, которые вы упомянули выше, имеют отношение ко всем сложным кавычкам и повторяющимся кодировкам, которые есть в вашем заявлении на печать.Я заменил ваше заявление о печати на map, чтобы упростить код.

Святое дерьмо, большая карта соединения, бла, не проще, вы можете подумать.Но на самом деле это проще, потому что каждая отдельная единица выражения меньше.Что легче понять и понять правильно?Что проще изменить и сохранить в правильном и согласованном поместье?

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 );

}
0 голосов
/ 10 августа 2010

Спасибо всем за помощь ... Это работает для меня.

  for my $Server(keys%MyItems){
    for my $BckupSet(keys%{$MyItems{$Server}}){
      for(sort keys%{$MyItems{$Server}{$BckupSet}}){
        print$_,'=>',$MyItems{$Server}{$BckupSet}{$_},';';
      }
      print"\n";
    }
  }
0 голосов
/ 07 августа 2010

Не отвечаю на вопрос, который вы задали, но мне это не кажется разумным.

Требуется массив хэшей, а не хэш хэшей.

Хэши не упорядочены, если вы хотите их упорядочить, используйте массив.

0 голосов
/ 07 августа 2010

Не проверено, но теоретически должно работать. Это напечатает строку вывода для каждого из ключей основного хеша MyItems. Если вы хотите, чтобы все это было в одной строке, вы можете просто удалить \ n или добавить другой разделитель.

foreach( values %MyItems ) {
     print "MyServer=>$_->{MyServer};MyLogdate=>$_->{MyLogdate};MyDataset=>$_->{MyDataset};backup-time=>$_->{backup-time};backup-status=>$_->{backup-status}\n";
}
...