2011-02-17 113 views
1

我有具有多列的製表符分隔數據。計算Perl中每列值w.r.t中的每個值的總和

我在第31列有OS名稱,第6和第7列有數據字節。我想要做的是計算每個獨特操作系統的總體積。

所以,我做在Perl是這樣的:

#!/usr/bin/perl 
use warnings; 

my @hhfilelist = glob "*.txt"; 
my %count =(); 

for my $f (@hhfilelist) { 
    open F, $f || die "Cannot open $f: $!"; 
    while (<F>) { 
     chomp; 
     my @line = split /\t/; 
     # counting volumes in col 6 and 7 for 31 
     $count{$line[30]} = $line[5] + $line[6];  
    } 
    close (F); 
} 

my $w = 0; 

foreach $w (sort keys %count) { 
    print "$w\t$count{$w}\n"; 
} 

因此,其結果會是這樣

Windows 100000 
Linux  5000 
Mac OSX  15000 
Android  2000 

但似乎在這個代碼中的一些錯誤,因爲所產生的值我得到的不是預期的。

我在做什麼錯?

+0

我會考慮起來 - 投票你的問題(風格,而不是錯誤本身),如果你真的提供樣本輸入導致問題,實際產出和預期產出 – DVK 2011-02-17 23:26:41

回答

6

看起來好像你並沒有實際增加計數 - 你用任何操作系統的最後一行的計數覆蓋任何操作系統的最後一個計數。

$count{$line[30]} = $line[5] + $line[6]; 

應該

$count{$line[30]} += $line[5] + $line[6]; 

作爲能夠全面提高你的代碼,但不影響它的正確性的其他注意事項:

  1. 請使用開放3個參數的形式和詞法文件句柄:

    open(my $filehandle, "<", $f) || die "Cannot open $f: $!"; 
    
  2. 如果您100%確定文件的字段內容中不包含帶引號的字段值或選項卡,則基於split的邏輯是可以的。對於真正複雜的X-分隔的文件,我會強烈建議使用Text::CSV_XS/Text::CSV CPAN模塊

  3. 不需要初始化%count$w變量 - 哈希將得到autoinitialized空哈希和$w被分配爲循環變量 - 您可能想要在循環中實際聲明它:foreach my $w (sort keys %count) {

  4. 請不要使用單字母變量。 $w在最後一個循環中沒有意義,而$os_name是清楚的。

+0

我們那會很尷尬。這樣一個基本的錯誤:)。感謝您的建議。 – sfactor 2011-02-17 23:24:25

+1

@sfactor - 如果這是你曾經犯過的最尷尬的錯誤,那麼認爲自己很幸運:)我的情況更糟 – DVK 2011-02-17 23:25:11

2
$count{$line[30]} = $line[5] + $line[6]; 

應該使用+ =運算符將行的總和總量,而不是將其設置總:

$count{$line[30]} += $line[5] + $line[6]; 
3

你表達

open F, $f || die "Cannot open $f: $!"; 

它有一個微妙的錯誤,最終會咬你,雖然可能不是今天。

||操作符比逗號運算符,以更高的優先級的左,所以這種表達實際上被解析爲

open F, ($f || die "Cannot open $f: $!") 

這是說,你會die$f有假(0,"" ,或undef)的值,而不是當open語句無法打開具有$f給出的名稱的文件。

做你的意思,你既可以使用括號:

open (F, $f) || die ... 

或使用替代低優先級or操作

open F, $f or die ... 

At times I have been bitten by this myself