2010-08-20 60 views
1

我有一個perl腳本只保留命名集合的最後一組記錄,而且我有一組以上的記錄。所以它將數據寫入散列並保留最後一組。我需要幫助打印出所有記錄。 謝謝!perl - 幫助散列和轉儲記錄

這裏是我的腳本的副本:

#!/usr/local/bin/perl 

use strict; 
use warnings; 
use Data::Dumper; 

my ($ServerName)[email protected]; 
my %MyItems; 
foreach my $ServerName(@ARGV){ 
    while (my $line = <>){ 
    chomp $line; 
       if ($line =~ m/.* \w+ \d{2} (\d{2}:\d{2}:\d{2}) \d{4}: ([^:]+):backup:/){ 
        my $ServerName = basename $ARGV, '.mydomain.com.backup-software.log'; #$ARGV is reading input from command line 
        my $BckupSet =$2; 
        my $BckupVal=$1; 
        $MyItems{$ServerName}{$BckupSet}->{'1-Server'} = $ServerName; 
        $MyItems{$ServerName}{$BckupSet}->{'2-BackupSet'} = $BckupSet; 
        $MyItems{$ServerName}{$BckupSet}->{'3-StartTime'} = $BckupVal; 

        if ($line =~ m/(backup-date)[:=](.+)/){ 
         my $BckupKey="4-DateStamp"; 
         my $BckupVal=$2; 
         $MyItems{$ServerName}{$BckupSet}->{$BckupKey} = $BckupVal; 
        } 

        if ($line =~ m/(backup-time)[:=](.+)/){ 
         my $BckupKey="5-Duration"; 
         my $BckupVal=$2; 
         $MyItems{$ServerName}{$BckupSet}->{$BckupKey} = $BckupVal; 
        } 
        if ($line =~ m/(backup-size)[:=](.+)/){ 
         my $BckupKey="6-Size"; 
         my $BckupVal=$2; 
         $MyItems{$ServerName}{$BckupSet}->{$BckupKey} = $BckupVal; 
        } 
        if ($line =~ m/(Backup succeeded)/){ 
         my $BckupKey="7-Status"; 
         my $BckupVal="Succeeded"; 
         $MyItems{$ServerName}{$BckupSet}->{$BckupKey} = $BckupVal; 
        } 
        if ($line =~ m/(ERROR)[:=](.+)/){ 
         my $BckupKey="8-Status"; 
         my $BckupVal="Unsuccessful"; 
         $MyItems{$ServerName}{$BckupSet}->{$BckupKey} = $BckupVal; 
         print "$BckupKey=$BckupVal\n" if debug; 
        } 
       } 
    } #endwhile 
    print Dumper(\%MyItems); 
    for my $ServerName(keys%MyItems){ 
    for my $BckupSet(keys%{$MyItems{$ServerName}}){ 
     for(sort keys%{$MyItems{$ServerName}{$BckupSet}}){ 
     #print$_,'=>',$MyItems{$ServerName}{$BckupSet}{$_},';'; 
     print$_,'=',$MyItems{$ServerName}{$BckupSet}{$_},';'; 
     } 
     print"\n"; 
    } 
    } 
} #END foreach 

下面是它看起來它轉儲時,如:

$VAR1 = { 
      'server1.name.colo' => { 
             'set1' => { 
                   '3-StartTime' => '07:08:15', 
                   '1-Server' => 'server1.name.colo', 
                   '6-Size' => '72.04 GB', 
                   '7-Status' => 'Succeeded', 
                   '4-DateStamp' => '20100820060002', 
                   '5-Duration' => '01:08:13', 
                   '2-BackupSet' => 'set1', 
                   '8-Status' => 'Unsuccessful' 
                  }, 
             'set2' => { 
                   '7-Status' => 'Succeeded', 
                   '6-Size' => '187.24 GB', 
                   '3-StartTime' => '01:51:25', 
                   '4-DateStamp' => '20100820000003', 
                   '1-Server' => 'server1.name.colo', 
                   '5-Duration' => '01:51:21', 
                   '2-BackupSet' => 'set2' 
                   }, 
             'set3' => { 
                   '3-StartTime' => '23:00:05', 
                   '4-DateStamp' => '20100814230003', 
                   '1-Server' => 'server1.name.colo', 
                   '8-Status' => 'Unsuccessful', 
                   '2-BackupSet' => 'set3' 
                  }, 
             'set4' => { 
                   '7-Status' => 'Succeeded', 
                   '6-Size' => '427.75 GB', 
                   '3-StartTime' => '00:43:20', 
                   '4-DateStamp' => '20100819200004', 
                   '1-Server' => 'server1.name.colo', 
                   '5-Duration' => '04:43:14', 
                   '2-BackupSet' => 'set4' 
                  }, 
             'set3' => { 
                   '7-Status' => 'Succeeded', 
                   '6-Size' => '46.42 GB', 
                   '3-StartTime' => '04:42:59', 
                   '4-DateStamp' => '20100820040002', 
                   '1-Server' => 'server1.name.colo', 
                   '5-Duration' => '00:42:56', 
                   '2-BackupSet' => 'set3' 
                  } 
             } 
     }; 
+0

究竟是什麼你希望看到什麼?多於1臺服務器? – cam 2010-08-20 22:02:12

回答

2

根據調試輸出,它看起來像你的問題在這裏:

if ($line =~ m/(ERROR)[:=](.+)/){ 
    my $BckupKey="8-Status"; 
    my $BckupVal="Unsuccessful"; 
    $MyItems{$ServerName}{$BckupSet}->{$BckupKey} = $BckupVal; 
    print "$BckupKey=$BckupVal\n" if debug; 
} 

要保存所有錯誤,您需要將該散列槽視爲對數組的引用:

if ($line =~ m/(ERROR)[:=](.+)/){ 
    my $BckupKey="8-Status"; 
    my $BckupVal="Unsuccessful"; 
    push @{ $MyItems{$ServerName}{$BckupSet}{$BckupKey} } => $BckupVal; 
    print "$BckupKey=$BckupVal\n" if debug; 
} 

在轉儲中,8-Status值將類似於

'8-Status' => [ 'Unsuccessful', 'Other error', 'Et cetera' ],

如果你想遍歷他們後,你會不喜歡

foreach my $err (@{ $MyItems{$ServerName}{$BckupSet}{$BckupKey} }) { 
    print "got $err\n"; 
} 

東西,只得到第一,你會寫

print $MyItems{$ServerName}{$BckupSet}{$BckupKey}[0], "\n"; 

的另一個問題是

foreach my $ServerName(@ARGV){ 
    while (my $line = <>){ 

要知道,while (<>) { ... }隱含遍歷在@ARGV命名的所有文件,所以它嵌套在一個循環內超過@ARGV沒有引起太大的意義。如果您的命令行的形式

$ readlogs server1 server2 server3 log1 log2

,那麼你會想從@ARGV服務器使用shift首先移除。將用戶想要的服務器主機名作爲區分參數可能會非常棘手。一個約定使用--信號選項處理結束,所以你可能

my @servers; 
while (@ARGV) { 
    my $server = shift; 
    last if $server eq "--" 
    push @servers => $server; 
} 

die "Usage: $0 server .. -- log ..\n" unless @ARGV; 

while (<>) { 
    # ... 
} 
+0

謝謝。我是否會將推送應用於所有其他條件?打印鍵? – jdamae 2010-08-20 22:27:15

+0

@ jda6one9使用'push'可以工作,但是你可能會被單元素數組激怒。這樣做的好處是永遠不會丟棄數據,但對於您想要做的事情可能過於寬容。 – 2010-08-20 22:53:22

+0

你之前幫我使用過 - > xargs -I {} ./myscript.pl {} jdamae 2010-08-20 23:14:01

2

這是題外話,但任何時候你需要深嵌套數據結構的代碼運行的越來越臃腫,難以閱讀的風險。操作簡單方便變量很長的路要走朝着精簡的東西,減輕代碼的閱讀器(從現在的你,3個月)必須執行許多精神的diff的:

# A convenience var. 
my $bs = $MyItems{$ServerName}{$BckupSet}; 

# The rest of your code can use the var. 
$bs->{'1-Server'} = $ServerName; 

而且,你有幾個if塊是做基本相同的事情。似乎服從某種調度表策略:

my @dispatch_table = (
    { 
     regex => qr/(backup-date)[:=](.+)/, 
     key => '4-DateStamp', 
     val => sub { $2 }, 
    }, 
    { 
     # etc. 
    }, 
); 

然後你if塊歸結爲這樣的事:

for my $dt (@dispatch_table){ 
    next unless $line =~ $dt->{regex}; 
    $bs->{ $dt->{key} } = $dt->{val}->(); 
} 
+0

@FM - 感謝您的提示!我在過去的幾個星期裏基本已經學會了perl。所以,我會盡我所能學習。 – jdamae 2010-08-21 03:44:05