2013-10-02 23 views
1

我有一個看起來像下面一個日誌文件:的Perl如果條件參數

4680 p4exp/v68  PJIANG-015394 25:34:19 IDLE none 
8869 unnamed p4-python  R integration semiconductor-project-trunktip-turbolinuxclient 01:33:52 IDLE none 
8870 unnamed p4-python  R integration remote-trunktip-osxclient 01:33:52 

有在同一個日誌文件,使得一些包含在結束閒置沒有,而一些沒有很多這樣的條目。我希望保留那些具有「R整合」和「空閒」的組合,並忽略其餘部分。我已經嘗試了下面的代碼,但沒有得到想要的結果。

#!/usr/bin/perl 
open (FH,'/root/log.txt'); 
my %stat; 
my ($killid, $killid_details); 
while ($line = <FH>) { 
    if ($line =~ m/(\d+)/){ 
      $killid = $1; 
    } 
    if ($line =~ /R integration/ and $line =~ /IDLE none/){ 
      $killid_details = $line; 
    } 
    $stat{$killid} = { 
      killid => $killid_details 
    }; 
} 
close (FH); 

我得到所有R集成這應該不會像8870應該被忽略的情況下,線(例如我得到8869,8870線)。

如果有任何錯誤,請通知我。我仍然在學Perl。謝謝。

+5

添加'使用嚴格的;'和'使用警告;'在你的程序,看看是否可以清理你的一些錯誤。 –

+0

這有什麼預期的結果? – fugu

+0

您需要添加'else {next; }''語句中的''子句,所以當它們不匹配時跳到下一行。我想你可能還需要改變你的'$ stat {$ killid}'任務,但很難說,因爲你沒有說出預期的結果。 – Barmar

回答

5

我做你的程序了幾個變化:始終把use strict;use warnings;

  • 。這些會吸收90%的錯誤。 (雖然不是這次)。
  • 當您打開一個文件時,您需要使用,如open my $fh, "<", $file or die qq(blah, blah, blah);或使用use autodie;(現在是首選)。就你而言,如果文件沒有打開,你的程序會繼續快樂地繼續。您需要測試open聲明是否有效。
  • 請注意我的open聲明。我使用文件句柄的變量。這是首選,因爲它不是全局的,並且更容易傳遞到子例程。另外請注意我使用三個參數open。這樣,如果您的文件名以一些奇怪的字符開頭,則不會遇到麻煩。
  • 當你聲明一個變量時,最好這樣做的範圍。這樣,當你不再需要變量時,變量就會超出範圍。我移動了$killid$killid_details以在循環內聲明。這樣,它們不再存在於循環之外。
  • 你需要更加小心你的正則表達式。如果短語IDLE none出現在您的行中的其他位置,該怎麼辦?你只需要它,如果它在行的末尾。

現在,這些問題你有:

  • ,當你閱讀都需要chomp線。在Perl中,讀取行尾的NL。使用chomp命令將其刪除。
  • 你的邏輯有點奇怪。如果您的線路中有一個數字,您可以設置$killid(我將其修改爲僅查看線路開頭的數字)。但是,即使沒有設置killid,您也可以輕鬆地繼續。在你的版本中,因爲你在循環之外聲明瞭$killid,它在每個循環中都有一個值。如果$killid沒有定義,我在這裏轉到下一個陳述。
  • 你有一個奇怪的定義你的散列。您正在散列中定義一個引用散列。沒有必要。我做了一個簡單的哈希。

這就是:

#! /usr/bin/env perl 
use strict; 
use warnings; 
use feature qw(say); 
use autodie; 
use Data::Dumper; 

open my $log_fh, '<', '/root/log.txt'; 

my %stat; 
while (my $line = <$log_fh>) { 
    chomp $line; 
    next if not $line =~ /^(\d+)\s+/; 
    my $killid = $1; 
    if ($line =~ /R\s+integration/ and $line =~ /IDLE\s+none$/){ 
     my $killid_details = $line; 
     $stat{$killid} = $killid_details; 
    } 
} 
close $log_fh; 

say Dumper \%stat; 
+0

謝謝你這麼好的解釋。對於像我這樣的初學者來說,一步一步的出色指導欣賞它! – deep

1

我想這可能是你想要什麼:

while (<FH>) { 
    next unless /^(\d+).*R integration.*IDLE none/; 
    $stat{$1} = $_; 
} 

的正則表達式應該被固定在一行的開頭,所以你不上線的任何位置匹配的數字。不需要執行多個正則表達式匹配,假設R integrationIDLE none的順序始終與示例中相同。如果沒有匹配,則需要使用next,因此不會處理不匹配的行。

而我懷疑你只是想將哈希條目的值設置爲字符串,而不是對另一個哈希的引用。