2010-11-11 27 views
2

J'ai écrit (avec beaucoup d'aide des autres) un awk command pour totaliser une colonne dans un fichier CSV. Malheureusement, j'ai appris après un certain googling que awk n'est pas génial pour gérer des fichiers CSV du fait que le séparateur n'est pas toujours le même (par exemple, les virgules doivent être ignorées lorsque vous entourez par des guillemets).Perl script (ou quoi que ce soit) pour totaliser colonne CSV

Il semble que peut-être un script Perl pourrait faire mieux. Serait-il possible d'avoir un script Perl d'une ligne (ou quelque chose de presque aussi succinct) qui réalise la même chose que cette commande awk qui totalise la 5ème colonne d'un fichier CSV? Je ne suis pas mariée à Perl en particulier, mais j'espérais éviter d'écrire un script PHP complet. À ce moment-là, j'aurais pu facilement écrire un script PHP, mais maintenant que je suis arrivé si loin, je veux voir si je peux le suivre.

Répondre

6

Vous devez utiliser un analyseur CSV décent pour gérer toutes les complexités du format CSV. Text::CSV_XS (ou Text::CSV si ce n'est pas disponible) est l'un des préférés.

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";}' 

Voici le code Perl réel, pour une meilleure lisibilité

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"; 

ci-dessus pourrait être raccourci en utilisant un peu moins bonne qualité mais plus dense 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"' 
+0

Je ne sais pas Perl, mais '} {' a l'air étrange dans votre version dense. Y-a-t-il des '' '' '' '' '' '' '' sous-entendus dans la boucle '-n' que vous n'avez pas à fournir? –

+0

Votre version avec 'cat' ne fonctionnerait pas bien avec un fichier CSV contenant un champ de chaîne multiligne. –

+0

@Dennis - '} {foo' est une version abrégée de' END {foo} ' –

3

Est-ce vous êtes opposé à l'utilisation d'un module Perl? Vous pouvez utiliser Text::CSV pour le faire facilement sans rouler votre propre analyseur.

Tutorial extrait modifié pour effectuer au total:

# ... 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"; 
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 

Pas une doublure, mais assez laconique.

0

Il existe un certain nombre d'outils qui font cela. Une recherche rapide pour 'cli csvparser' m'a conduit à plusieurs outils (que je ne peux apparemment pas lier - probablement pour éviter le spam).

J'ai installé le premier que j'ai trouvé - csvtool - et j'ai pu faire une ligne de commande similaire à la vôtre et obtenir un total.

0

assez court (et rapide) solution:

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