0

可能であれば、ハッシュ/ハッシュ参照から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

追加されたばかり(2010年8月7日):私が使用している生のログファイルのサンプル:(ソースログのより良い表現を提供するために最近追加されました)

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

4 に答える 4

1

私はあなたのコードを見てしばらく時間を費やしました、そして私はそれを理解したと思います。

これに答えるのが難しい理由は、意図せずに赤いニシン、つまりデータダンパーの出力を植えたためです。

$VAR1 = 'server1';それがどのように表示されるかに注意してください$VAR2 = { blah };

あなたはそのようにダンパーを呼んだ: print Dumper %MyItems;

問題は、Perlがリストをフラット化するため、Dumperが値のリストをダンプすることを望んでいることです。複雑な構造は、参照によって渡される必要があります。したがって、次のようにDumperを呼び出す必要があります。

print Dumper \%MyItems;

これは全体の構造を示しています。

以前にダンパーを呼び出したときに、データ構造の1つのレイヤーを誤って削除しました。提案されたソリューションと独自のコードは、このストリップされた構造で動作しています。

ここでは、ネストの追加レイヤーを処理するためにいくつかのコードを追加しました(そして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";
    }
}

たくさんの質問があり、いくつかの概念について頭を悩ませるのに助けが必要なようです。コードの改善を支援するために、PerlWisdomのSeekersのPerlmonksにリクエストを投稿することをお勧めします。SOは焦点を絞った質問には最適ですが、PMはコードのやり直しに適しています。

**元の回答:**

再現できない解析の問題を回避するために、%MyItems提供されたDumperの出力に設定しました。

あなたが上で言及したあなたの警告は、あなたがあなたの印刷ステートメントに持っているすべての複雑な引用と繰り返しのコーディングと関係があります。mapコードを簡略化するために、printステートメントをに置き換えました。

神聖ながらくた、大きな結合マップの何とかは単純ではありません、あなたは考えているかもしれません。しかし、実際には、個々の表現単位が小さいため、より単純です。理解し、正しく理解するのが簡単なことは何ですか?正しく一貫したマナーで変更および維持するのが簡単なものは何ですか?

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

}
于 2010-08-07T07:21:21.137 に答える
0

テストされていませんが、理論的には機能するはずです。これにより、メインのMyItemsハッシュの各キーの出力行が出力されます。すべてを1行にしたい場合は、\ nを削除するか、他の区切り文字を追加するだけです。

foreach( values %MyItems ) {
     print "MyServer=>$_->{MyServer};MyLogdate=>$_->{MyLogdate};MyDataset=>$_->{MyDataset};backup-time=>$_->{backup-time};backup-status=>$_->{backup-status}\n";
}
于 2010-08-07T02:17:15.103 に答える
0

あなたが尋ねた質問に答えていませんが、これは私には賢明ではないようです。

ハッシュのハッシュではなく、ハッシュの配列が必要です。

ハッシュは順序付けられていません。順序付けする場合は、配列を使用してください。

于 2010-08-07T08:09:33.037 に答える
0

みんなの助けを借りてくれてありがとう...これは私にとってはうまくいく。

  for my $Server(keys%MyItems){
    for my $BckupSet(keys%{$MyItems{$Server}}){
      for(sort keys%{$MyItems{$Server}{$BckupSet}}){
        print$_,'=>',$MyItems{$Server}{$BckupSet}{$_},';';
      }
      print"\n";
    }
  }
于 2010-08-10T16:49:13.473 に答える