web-dev-qa-db-fra.com

Comment analyser des fichiers CSV sur la ligne de commande Linux?

Comment analyser des fichiers CSV sur la ligne de commande Linux?

Pour faire des choses comme:

csvparse -c 2,5,6 filename

pour extraire les champs des colonnes 2, 5 et 6 de toutes les lignes.

Il devrait être en mesure de gérer le format de fichier csv: http://tools.ietf.org/html/rfc418 ce qui signifie des guillemets et des échappements entre guillemets internes, le cas échéant , donc pour un exemple de ligne avec 3 champs:

field1,"field, number ""2"", has inner quotes and a comma",field3

de sorte que si je demande le champ 2 pour la ligne ci-dessus, je reçois:

field, number "2", has inner quotes and a comma

J'apprécie qu'il existe de nombreuses solutions, Perl, Awk (etc.) à ce problème, mais j'aimerais un outil de ligne de commande bash natif qui ne nécessite pas que j'invoque un autre environnement de script ou que j'écrive du code supplémentaire (!).

36
Joel

Mon éditeur de flux FOSS CSV CSVfix fait exactement ce que vous voulez. Il existe un programme d'installation binaire pour Windows et une version compilable (via un makefile) pour UNIX/Linux.

20
anon

csvtool est vraiment bon. Disponible dans Debian/Ubuntu (apt-get install csvtool). Exemple:

csvtool namedcol Account,Cost input.csv > output.csv

Voir page de manuel CSVTool pour des conseils d'utilisation.

22
Lari Hotari

Comme suggéré par @Jonathan dans un commentaire, il existe un module pour python qui fournit l'outil de ligne de commande csvfilter. Il fonctionne comme cut, mais gère correctement les colonnes CSV en citant:

csvfilter -f 1,3,5 in.csv > out.csv

Si vous avez python (et vous devriez), vous pouvez l'installer simplement comme ceci:

pip install csvfilter

Plus d'informations sur https://github.com/codeinthehole/csvfilter/

10
studgeek

J'ai trouvé csvkit utile, il est basé sur le module python csv et a beaucoup d'options pour analyser des fichiers csv complexes.

Bien que cela semble être un peu lent. J'obtiens 4 Mo/s (avec 100% de processeur) lors de l'extraction d'un champ d'un csv de 7 Go avec 5 colonnes.

Pour extraire la 4e colonne de file.csv

csvcut -c 4 file.csv
7
cjg

Essayez crush-tools , ils sont parfaits pour manipuler des données délimitées. Cela ressemble exactement à ce que vous recherchez.

5
jmanning2k

J'ai également écrit un de ces outils (UNIX uniquement) appelé csvprintf . Il peut également être converti en XML de manière en ligne.

3
Archie

Ma réaction instinctive serait d'écrire un wrapper de script autour du module csv de Python (s'il n'y a pas déjà une telle chose).

2
Jeremy Cantrell

Pour un wrapper super léger autour du module csv de Python, vous pouvez regarder pluckr .

2
philadams

Cela ressemble à un travail pour awk.

Vous aurez très probablement besoin d'écrire votre propre script pour vos besoins spécifiques, mais this site a un dialogue sur la façon de procéder.

Vous pouvez également utiliser l'utilitaire de découpe pour supprimer les champs.

Quelque chose comme:

cut -f 2,5,6 -d , filename

où l'argument -f est le champ souhaité et -d le délimiteur souhaité. Vous pouvez ensuite trier ces résultats, trouver les résultats uniques ou utiliser tout autre utilitaire bash. Il y a une vidéo sympa ici sur l'utilisation des fichiers CSV depuis la ligne de commande. Seulement environ une minute, je jetais un coup d'œil.

Cependant, je suppose que vous pouvez regrouper l'utilitaire cut avec awk et ne pas vouloir l'utiliser. Je ne sais pas vraiment ce que vous entendez exactement par commande bash native, donc je vais quand même le suggérer.

1
samoz

ffe est un autre excellent outil. Il vous oblige à créer un fichier de configuration pour la plupart des tâches non triviales. L'avantage est qu'il est très flexible et peut gérer toutes sortes de structure, de logique et de formatage que d'autres outils ne peuvent pas.

J'aime utiliser csvtool pour les travaux rapides et utiliser ffe pour les travaux complexes ou qui nécessitent des répétitions fréquentes.

1
Animism

Script Perl (nécessite Text :: CSV_XS):

#!/usr/bin/Perl

use strict;
use warnings;

use Getopt::Long;
my @opt_columns;
GetOptions("column=i@" => \@opt_columns)
  or die "Failed parsing options\n";
die "Must give at least one --column\n" if int(@opt_columns) == 0;
@opt_columns = map { $_-1 } @opt_columns; # convert 1-based to 0-based

use Text::CSV_XS;
my $csv = Text::CSV_XS->new ( { binary => 1 } );

open(my $stdin, "<-") or die "Couldn't open stdin\n";
open(my $stdout, ">-") or die "Couldn't open stdout\n";
while (my $row = $csv->getline($stdin)) {
    my @nrow = @{$row}[@opt_columns];
    $csv->print($stdout, \@nrow);
    print "\n";
}

Mettez-le dans un fichier csvcut.pl.

Exemple de prendre uniquement les colonnes 3 et 4:

cat foo.csv | ./csvcut.pl --c 3 --c 4

Cela ne citera que les colonnes qui nécessitent des guillemets, donc si une colonne d'entrée a "Bar" (avec guillemets), elle sortira Bar (sans guillemets).

0
dfrankow

Un rapide google révèle un script awk qui semble gérer les fichiers csv.

0
RobS