在一系列行中计算空间分隔文本文件中的数值

时间:2009-04-22 05:41:55

标签: perl math shell text

我有一个包含以下值的文件:

for 3 threads:
Average time taken for API1 is: 19097.7 nanoseconds.
Average time taken for API2 is: 19173.1 nanoseconds.
Average time taken for API2 is: 19777.7 nanoseconds.
Average time taken for API2 is: 19243.1 nanoseconds.
Average time taken for API1 is: 19737.7 nanoseconds.
Average time taken for API2 is: 19128.1 nanoseconds.
for 5 threads:
Average time taken for API1 is: 19097.7 nanoseconds.
Average time taken for API2 is: 19173.1 nanoseconds.
Average time taken for API2 is: 19777.7 nanoseconds.
...

我希望计算1API线和2API线的总和,并将它们相加。 另一个要求是我也想在单独的基础上找出每个线程。有没有办法使用perl,sed,awk或只是shell脚本?

我目前得到的是:

cat result | grep API1 | awk {'print $7'}

3 个答案:

答案 0 :(得分:2)

您可以使用grep en awk的组合。 grep只选择带有数据的行(API在哪里)和awk用于计数。

grep API file | awk '{ arr[$5]+=$7 } END {for (i in arr) {print i,arr[i]}   } ' -

(用文件名更改文件或从stdin读取删除)

如果你想计算不同的金额,你可以这样做

awk '{ if($1 == "for") id = $2; else arr[id $5]+=$7 } END {for (i in arr) {print i,arr[i]}   } ' testfile

输出:

5API1 19097.7
5API2 38950.8
3API1 38835.4
3API2 77322

答案 1 :(得分:0)

简短且不可读:

perl -lane 'END{&h}sub h{print"\t$_ => $h{$_}"for keys%h;%h=()}&h,print,next if/^for/;$h{$F[4]}+=$F[6]' data

可读,但必须是剧本:

#!/usr/bn/perl

use strict;
use warnings;

my %counts;
my $thread = "undefined";
while (<>) {
    if (/^for ([0-9]+)/) {
        $thread = $1;
        next;
    }
    my ($item, $time) = /for (\S+) is: (\S+) nano/;
    $counts{$thread}{$item} += $time;
}

for my $thread (sort { $a <=> $b } keys %counts) {
    print "for $thread threads:\n";
    for my $item (sort keys %{$counts{$thread}}) {
        print "\t$item => $counts{$thread}{$item}\n";
    }
}

答案 2 :(得分:0)

我不明白你的上一个要求( 没有指定线程),但我会为你提供一个设置信息并满足我可以的要求了解。数据被分解,因此您可以访问它。虽然我不明白你如何使用'for x threads:'行,但它至少被捕获了,所以你可以使用它。

use List::Util qw<sum>;

my $fh = FileHandle->new( PATH_TO_DATAFILE );
my $data 
    = { trial_times => []
      , totals      => {}
      };
my $precision = 0;

while ( <$fh> ) { 
    if ( m/^for (\d+) threads:/ ) { 
        push @{$data->{trial_times}}, {};
    }
    elsif ( m/^Average time taken for (API\w+) is: (\d+\.(\d+)) nanoseconds./ ) {
        push @{$data->{trial_times}[-1]{$1}}, $2;
        push @{ $data->{totals}->{$1} }, $2;
        $precision = length $3 if length $3 > $precision;
    }
}

### $data

foreach my $api ( keys %{ $data->{totals} } ) { 
    my @list = @{ $data->{totals}{$api} };
    my $sum  =sum @list;

    printf "Sum for %d runs of API $api: %0.${precision}f (Average: %0.${precision}f)\n"
         , scalar @list, $sum, $sum / scalar @list
         ;
}

my @combined = map { @$_ } values %{$data->{totals}};
### @combined
my $sum      = sum @combined;
printf "Combined %d runs for %0.${precision}f total (Average: %0.${precision}f)\n"
    , scalar @combined, $sum, $sum / scalar @combined
    ;