2012-11-06 172 views
2

首先,如果您覺得這是重複的,我表示歉意。我環顧四周,發現了一些非常相似的問題,但我要麼迷路了,要麼不是我認爲我需要的東西,因此不能提出適當的實施方案。Perl - 從文本文件中解析塊

問題:

所以我有一個包含由另一個腳本生成的條目一個txt文件(我可以編輯如何生成這些條目的格式,如果你能提出一個更好的辦法來設置格式):

SR4 Pool2 
11/5/2012 13:45 
---------- 
Beginning Wifi_Main(). 

SR4 Pool2 
11/8/2012 8:45 
---------- 
This message is a 
multiline message. 

SR4 Pool4 
11/5/2012 14:45 
---------- 
Beginning Wifi_Main(). 

SR5 Pool2 
11/5/2012 13:48 
---------- 
Beginning Wifi_Main(). 

而且我做了一個Perl腳本解析文件:

#!C:\xampp-portable\perl\bin\perl.exe 

use strict; 
use warnings; 
#use Dumper; 

use CGI 'param','header'; 
use Template; 
#use Config::Simple; 

#Config::Simple->import_from('config.ini', \%cfg); 

my $cgh = CGI->new; 
my $logs = {}; 
my $key; 

print "Content-type: text/html\n\n"; 

open LOG, "logs/Pool2.txt" or die $!; 


while (my $line = <LOG>) { 
    chomp($line); 

} 

print $logs; 

close LOG; 

我的目標是在看起來像這樣結束的哈希:

$logs = { 
    SR4 => { 
      Pool2 => { 
       { 
        time => '11/5/2012 13:45', 
        msg => 'Beginning Wifi_NDIS_Main().', 
       }, 
       { 
        time => '11/8/2012 8:45', 
        msg => 'This message is a multiline message.', 
       }, 
      }, 
      Pool4 => { 
       { 
        time => '11/5/2012 13:45', 
        msg => 'Beginning Wifi_NDIS_Main().', 
       }, 
      }, 
    }, 
    SR5 => { 
      Pool2 => { 
       { 
        time => '11/5/2012 13:45', 
        msg => 'Beginning Wifi_NDIS_Main().', 
       }, 
      }, 
    }, 

};

要做這件事的最好方法是什麼?我應該更改生成的日誌的格式以使其更容易嗎?如果您需要更多信息,請詢問。先進的謝謝你。 :)

回答

2

如果你所能輸出爲XML,閱讀它會與XML::Simple

+0

嗯。當我有機會的時候,我會更加關注這個問題,謝謝。 – Dylan

2

格式embarrasingly容易是沒有意義的。你在第三級使用了散列,但是你沒有爲這些值指定鍵。我假設它應該是一個數組。

my %logs; 
{ 
    local $/ = ""; # "Paragraph mode" 
    while (<>) { 
     my @lines = split /\n/; 
     my ($x, $y) = split ' ', $lines[0]; 
     my $time = $lines[1]; 
     my $msg = join ' ', @lines[3..$#lines]; 
     push @{ $logs{$x}{$y} }, { 
     time => $time, 
     msg => $msg, 
     }; 
    } 
} 

我應該改變生成的日誌

你的時間戳似乎是曖昧的格式。在大多數時區,一年的一個小時會重複。

+0

「您的時間戳看起來含糊不清,在大多數時區,一年中的一個小時會重複。」 這是什麼意思?你如何建議我做一個時間戳?更精確? – Dylan

+0

@Dylan,在這裏,由於時鐘變化,在'11/4/2012 0:00'後90分鐘和同一時間後150分鐘,時鐘讀取'11/4/2012 1:30'。如果需要,您可以包含來自UTC的偏移量以消除歧義。 – ikegami

0

雖然Karthik T使用XML的想法很有意義,我也會考慮它,但我不確定這是否是最佳路線。第一個問題是首先將它放在XML格式中。

其次是XML格式可能不那麼容易被解析。當然,XML :: Simple模塊將一次性讀取整個事件,然後您必須解析XML數據結構本身。

如果您可以根據需要設置輸出,請使用易於解析的格式。我喜歡使用前綴數據標識符。在下面的例子中,每條數據都有自己的標識符。該ER:告訴我,當我達到創紀錄的末尾:

DT: 11/5/2012 13:35 
SR: SR4 
PL: Pool2 
MG: Beginning Wifi_Main(). 
ER: 
DT: 1/8/2012 8:45 
SR: SR4 
PL: Pool2 
MG: This message is a 
MG: multiline message. 
ER: 

解析這個輸出是直截了當:

my %hash; 
while ($line = <DATA>) { 
    chomp $line; 
    if (not $line eq "ER:") { 
     my ($key, $value) = split (": ", $line); 
     $hash{$key} .= "$value "; #Note trailing space! 
    } 
    else { 
     clean_up_hash (\%hash); #Remove trailing space on all values 
     create_entry (\%log, \%hash); 
     %hash =(); 
    } 
} 

我喜歡用每當我開始越來越複雜的數據結構類,我可能會創造一個Local::Log類和子類來存儲日誌的每一層。然而,這不是絕對必要的,也不是你的問題的一部分。不過,我會使用一個create_entry子例程來保持確定日誌中該條目​​在循環內所處位置的邏輯。

注意:我在每段數據後面追加一個空格。我這樣做是爲了使代碼更簡單,因爲你的一些消息可能需要多行。還有其他方法可以解決這個問題,但我試圖儘可能保持循環儘可能乾淨,並儘可能減少陳述。