我有多列的制表符分隔数据.
我在第31列中有操作系统名称,在第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";
}
Run Code Online (Sandbox Code Playgroud)
所以,结果会是这样的
Windows 100000
Linux 5000
Mac OSX 15000
Android 2000
Run Code Online (Sandbox Code Playgroud)
但是在这段代码中似乎有一些错误,因为我得到的结果值并不像预期的那样.
我究竟做错了什么?
看起来你实际上并没有添加计数 - 你用该操作系统最后一行的计数覆盖任何操作系统的最后计数.
$count{$line[30]} = $line[5] + $line[6];
Run Code Online (Sandbox Code Playgroud)
应该
$count{$line[30]} += $line[5] + $line[6];
Run Code Online (Sandbox Code Playgroud)
作为可以改善整体代码但不影响其正确性的其他注意事项:
请使用3参数形式的open和Lexical文件句柄:
open(my $filehandle, "<", $f) || die "Cannot open $f: $!";
Run Code Online (Sandbox Code Playgroud)如果您100%确定您的文件在字段内容中不包含带引号的字段值或选项卡,则split基于您的逻辑是正常的.对于非常复杂的X分隔文件,我强烈建议使用Text::CSV_XS/ Text::CSVCPAN模块
不需要初始化%count或$w变量 - 哈希将自动初始化为空哈希,$w并被分配为循环变量 - 您可能希望实际在循环中声明它:foreach my $w (sort keys %count) {
请不要使用单字母变量.$w在最后一个循环中没有意义,但$os_name很清楚.