2010-08-07 44 views
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 

剛剛添加(8/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 
+0

設置詞彙'$ ARGV'讓我很緊張。你有這樣做的理由嗎? '$ ARGV'是一個特殊的變量,它包含'<>'正在讀取的文件的名稱。設置它,更不用說它像詞彙似乎要求麻煩。 – daotoad 2010-08-07 07:26:09

+0

@daotoad - 這與我發佈的另一個問題有關。 http://stackoverflow.com/questions/3427528/perl-help-passing-looping-in-arguments-from-file-or-within-a-separate-perl-data 我將需要通過閱讀多( 1)日誌文件。 – jdamae 2010-08-07 15:31:45

回答

0

感謝大家在他們的幫助下投球...... 這對我有用。

for my $Server(keys%MyItems){ 
    for my $BckupSet(keys%{$MyItems{$Server}}){ 
     for(sort keys%{$MyItems{$Server}{$BckupSet}}){ 
     print$_,'=>',$MyItems{$Server}{$BckupSet}{$_},';'; 
     } 
     print"\n"; 
    } 
    } 
0

未經測試,但它應該在理論上工作。這將爲主MyItems散列的每個鍵打印輸出行。如果你想把它全部放在一行上,你可以放下\ n或添加一些其他分隔符。

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

@Cfreak - 感謝您的幫助,但沒有輸出:-( – jdamae 2010-08-07 02:46:44

+1

您是否收到錯誤?我測試了它並獲得了預期的輸出結果,您應該將其與現有代碼結合使用。 。 – Cfreak 2010-08-07 02:54:29

+0

@Cfreak - 是的,錯誤,我甚至試過只打印一個,沒有運氣。 ErrorMesg: Bareword「backup」不允許使用「strict subs」 ./hashtst2.pl第56行。 當在./hashtst2.pl第56行使用「strict subs」時,不允許使用Bareword「backup」。 在./hashtst2使用「strict subs」時,不允許使用Bareword「status」。 pl line 56. 我編輯了代碼以顯示包括變量在內的整個腳本。 – jdamae 2010-08-07 03:00:22

1

我花了一些時間看你的代碼,我想我已經想通了。

這個難以回答的原因是,你無意中種下了一條紅鯡魚 - 數據傾卸輸出。

注意它是如何顯示$VAR1 = 'server1';,然後$VAR2 = { blah };

你叫自卸車像這樣:print Dumper %MyItems;

的問題是,自卸車希望值的列表傾倒,因爲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"; 
    } 
} 

它看起來像你有很多的問題,需要一些幫助,讓你的頭圍繞着一些概念。我建議你在Perl Wisks的Perlkers上發佈一個請求,以幫助改進你的代碼。 SO非常適合集中討論問題,但PM更適合代碼返工。

**原來的答覆:**

要解決這個問題,我不能複製任何解析的問題,我只設置%MyItems爲您提供翻車機的輸出。

您上面提到的警告與您在打印聲明中使用的所有複雜的引用和重複編碼有關。我用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

@daotoad - 感謝您的輸入。不,沒有理由,除了我從這個論壇上選擇的建議,我是編程和使用Perl的新手,所以對我來說最好的實踐將是有益的。 – jdamae 2010-08-07 14:23:25

+0

@daotoad - 我在我的問題中添加了一個日誌文件的樣本,我我正在通過收集我的數據集,它使用正則表達式來填充散列,作爲perl的新手,它讓我很難理解哪個更適合使用(散列或散列,散列散列),個人而言,清晰的可視化表示如果你能爲我的技能水平提供一個最好的方法,我可以使用,謝謝!! – jdamae 2010-08-07 14:44:41

+0

@daotoad - 不幸的是,我運行perl 5.8 :-( 無法找到功能。pm – jdamae 2010-08-07 17:04:49

0

不回答你問的問題,但這對我來說似乎不明智。

你想要一個散列數組而不是散列散列。

散列沒有排序,如果你想讓它們排序然後使用一個數組。