2011-02-17 96 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