Perl脚本(或任何内容)总计CSV列

时间:2010-11-11 22:01:22

标签: perl csv awk

我写了(在其他人的帮助下)awk command来汇总CSV文件中的一列。不幸的是,我在谷歌搜索后得知awk处理CSV文件并不好,因为分隔符并不总是相同(即当用引号括起来时应忽略逗号)。

似乎Perl脚本可能做得更好。是否可以使用单行Perl脚本(或几乎简洁的东西)实现与总计CSV文件第5列的awk命令相同的操作?

cat file.csv | awk -F "\"*,\"*" '{s+=$5} END {printf("%01.2f\n", s)}'

我并没有特别嫁给Perl,但我希望避免编写一个完整的PHP脚本。这时我可以轻松编写一个PHP脚本,但是现在我已经走到这一步了,我想看看我是否能够完成它。

5 个答案:

答案 0 :(得分:6)

您需要使用合适的CSV解析器来处理CSV格式的所有复杂性。 Text::CSV_XS(或Text::CSV如果不可用)是首选之一。

perl -e '{use Text::CSV_XS; my $csv=Text::CSV_XS->new(); open my $fh, "<", "file.csv" or die "file.csv: $!"; my $sum = 0; while (my $row = $csv->getline ($fh)) {$sum += $row->[4]}; close $fh; print "$sum\n";}'

这是实际的Perl代码,以提高可读性

use Text::CSV_XS; # use the parser library
my $csv = Text::CSV_XS->new(); # Create parser object
open my $fh, "<", "file.csv" or die "file.csv: $!"; # Open the file. 
my $sum = 0; 
while (my $row = $csv->getline ($fh)) { # $row is array of field values now
    $sum += $row->[4];
}
close $fh; 
print "$sum\n";

通过使用质量稍差但更密集的Perl来缩短上述内容

cat file.csv | perl -MText::CSV_XS -nae '$csv=Text::CSV_XS->new(); 
               $csv->parse($_); @f=$csv->fields(); $s+=$f[4]} { print "$s\n"'

答案 1 :(得分:3)

您是否反对使用Perl模块?您可以使用Text::CSV轻松完成此操作,而无需滚动自己的解析器。

Tutorial代码段已更改为执行总计:

# ... some tutorial code ommited
while (<CSV>) {
    if ($csv->parse($_)) {
        my @columns = $csv->fields();
        $total += $columns[4];
    } else {
        my $err = $csv->error_input;
        print "Failed to parse line: $err";
    }
}
print "total: $total\n";

答案 2 :(得分:1)

的Python

import csv
with open( "some_file.csv", "rb" ) as source:
    rdr= csv.reader( source )
    col_5= 0
    for row in rdr:
        col_5 += row[5]
print col_5

不是单行,但非常简洁。

答案 3 :(得分:0)

有很多工具可以做到这一点。快速搜索“cli csvparser”会引导我使用几种工具(我显然无法链接到这些工具 - 可能是为了防止发送垃圾邮件)。

我安装了我发现的第一个 - csvtool - 并且能够执行与您类似的命令行并获得总数。

答案 4 :(得分:0)

非常简短(快速)的解决方案:

perl -MText::CSV_XS -E'$c=new Text::CSV_XS;$s+=$r->[4]while$r=$c->getline(*ARGV);say$s' file.csv