2009-11-16 127 views
0

下面是示例CSV文件如何在每行和每列中添加值並在Perl中打印最後?

date,type1,type2,..... 
2009-07-01,n1,n2,..... 
2009-07-02,n21,n22,.... 
and so on... 

我想每一行和每一行的結束和底部的每一列和打印中添加值。即

date,type1,type2 
2009-07-01,n1,n2,.....row_total1 
2009-07-02,n21,n22,....row_total2 
Total,col_total1,col_total1,......total 

請建議。

回答

1

像JB的perlgolf候選人,除了打印端線總數和標籤。

#!/usr/bin/perl -alnF, 
use List::Util qw(sum); 
chomp; 
push @F, $. == 1 ? "total" : sum(@F[1..$#F]); 
print "$_,$F[-1]"; 
for (my $i=1;$i<@F;$i++) { 
    $totals[$i] += $F[$i]; 
} 
END { 
    $totals[0] = "Total"; 
    print join(",",@totals); 
}; 
1

這是否需要在Perl腳本中完成?在Perl中沒有「快速和骯髒」的方法。您將需要讀取文件,累計您的總數,並將文件寫回(逐行處理輸入和輸出將是最清潔的)。

如果這是一次性報告,或者您正在以合格的用戶羣進行工作,您最想要的數據可以通過電子表格程序(如Excel)輕鬆生成。

0

以下Perl在Perl中做了你想要的東西,它不是很優雅,但它的工作原理是:-) 以輸入文件爲參數調用腳本,產生stdout。

chop($_ = <>); 

print "$_,Total\n"; 

while (<>) { 

    chop; 
    split(/,/); 
    shift(@_); 

    $sum = 0; 

    for ($n = 0; 0 < scalar(@_); $n++) { 
     $c = shift(@_); 
     $sum += $c; 
     $sums[$n] += $c; 
    } 

    $total += $sum; 

    print "$_,$sum\n"; 
} 

print "Total"; 

for ($n = 0; $n <= $#sums; $n++) { 

    print "," . $sums[$n]; 
} 

print ",$total\n"; 

編輯:固定爲0的值。

輸出是這樣的:

date,type1,type2,type3,Total 
2009-07-01,1, 2, 3,6 
2009-07-02,4, 5, 6,15 
Total,5,7,9,21 
+0

謝謝,這工作,但直到0變得可以計算值。你能否建議如何添加0值的字段。 – Space 2009-11-16 14:27:12

+0

糟糕,修正了 – rsp 2009-11-16 15:43:38

+0

請勿使用'chop',請使用'chomp'。 – 2009-11-17 01:28:50

3

那麼優雅和更短:

$ perl -plaF, -e '$r=0;$r+=$F[$_],$c[$_]+=$F[$_]for 1..$#F;$_.=",$r";END{$c[0]="Total";print join",",@c}' 

快速和骯髒的,但應該做的伎倆基本情況。對於更復雜的任何事情,請使用Text :: CSV和實際腳本。

的擴展版本,因爲它的開始有點毛毛:

#! perl -plaF, 
$r=0; 
$r+=$F[$_], $c[$_]+=$F[$_] for 1..$#F; 
$_.=",$r"; 
END { $c[0]="Total"; print join ",", @c }' 
+0

我認爲你的意思是'perl -plaF',(在逗號之前的反斜槓可能在某些shell中是必需的) – 2009-11-16 14:21:42

+0

準確地說。這和其他一些修復;)謝謝 – 2009-11-16 14:23:29

+0

謝謝,這給了我每列的附加值,如何使用這個每行。 – Space 2009-11-16 14:26:18

2

這裏,你可以輕鬆地建立根據您的要求在一個簡單的方法:

use strict; 
use warnings; 
use 5.010; 
use List::Util qw(sum); 
use List::MoreUtils qw(pairwise); 
use Text::ParseWords; 

our ($a, $b); 
my @header = parse_csv(scalar <DATA>); 
my @total = (0) x @header; 
output_csv(@header, 'row_total'); 

for my $line (<DATA>) { 
    my @cols = parse_csv($line); 
    my $label = shift @cols; 
    push @cols, sum @cols; 
    output_csv($label, @cols); 
    @total = pairwise { $a + $b } @total, @cols; 
} 

output_csv('Total', @total); 

sub parse_csv { 
    chomp(my $data = shift); 
    quotewords ',', 0, $data; 
} 

sub output_csv { say join ',' => @_ } 

__DATA__ 
date,type1,type2 
2009-07-01,1,2 
2009-07-02,21,22 

產出預期:

date,type1,type2,row_total 
2009-07-01,1,2,3 
2009-07-02,21,22,43 
Total,22,24,46 

有些事情要帶走從上面是使用List::UtilList::MoreUtils

# using List::Util::sum 
my $sum_of_all_values_in_list = sum @list; 

# using List::MoreUtils::pairwise 
my @two_arrays_added_together = pairwise { $a + $b } @array1, @array2; 

而且同時我在我的例子中使用Text::ParseWords你真的應該考慮使用Text::CSV。這些模塊涵蓋了更奇怪的CSV邊緣情況,並且還提供了正確的CSV組合(我的output_csv()子非常天真!)。

/I3az/

0

每當我與CSV工作,我用的是AnyData模塊。它可能會增加一些開銷,但它使我不會犯錯誤(「哦,廢話,那個日期欄被引用,並且有逗號!?」)。
你會看起來像這樣的過程:

use AnyData; 
my @columns = qw/date type1 type2 type3/; ## Define your input columns. 
my $input = adTie('CSV', 'input_file.csv', 'r', {col_names => join(',', @columns)}); 
push @columns, 'total'; ## Add the total columns. 
my $output = adTie('CSV', 'output_file.csv', 'o', {col_names => join(',', @columns)}); 
my %totals; 
while (my $row = each %$input) { 
    next if ($. == 1); ## Skip the header row. AnyData will add it to the output. 
    my $sum = 0; 
    foreach my $col (@columns[1..3]) { 
     $totals{$col} += $row->{$col}; 
     $sum += $row->{$col}; 
    } 
    $totals{total} += $sum; 
    $row->{total} = $sum; 
    $output->{$row->{date}} = $row; 
} 
$output->{Total} = \%totals; 
print adDump($output); ## Prints a little table to see the data. Not required. 
undef $input; ## Close the file. 
undef $output; 

輸入:

date,type1,type2,type3 
2009-07-01,1,2,3 
2009-07-03,31,32,33 
2009-07-06,61,62,63 
"Dec 31, 1969",81,82,83 

輸出:

date,type1,type2,type3,total 
2009-07-01,1,2,3,6 
2009-07-03,31,32,33,96 
2009-07-06,61,62,63,186 
"Dec 31, 1969",81,82,83,246 
Total,174,178,182,534 
相關問題