Existe-t-il un outil de ligne de commande robuste pour le traitement des fichiers csv?

47

Je travaille avec des fichiers CSV et ai parfois besoin de vérifier rapidement le contenu d'une ligne ou d'une colonne à partir de la ligne de commande. Dans de nombreux cas cut, head, tailet amis feront le travail; Cependant, couper ne peut pas facilement traiter avec des situations telles que

"this, is the first entry", this is the second, 34.5

Ici, la première virgule fait partie du premier champ, mais en cut -d, -f1désaccord. Avant d’écrire moi-même une solution, je me demandais si quelqu'un connaissait un bon outil qui existe déjà pour ce travail. Il devrait au moins pouvoir gérer l'exemple ci-dessus et renvoyer une colonne à partir d'un fichier au format CSV. D'autres fonctionnalités souhaitables incluent la possibilité de sélectionner des colonnes en fonction des noms de colonne donnés dans la première ligne, la prise en charge d'autres styles de citation et la prise en charge de fichiers séparés par des tabulations.

Si vous ne connaissez pas un tel outil, mais avez des suggestions concernant la mise en œuvre d'un tel programme en Bash, Perl ou Python, ou dans d'autres langages de script courants, ces suggestions ne me dérangeraient pas.

Steven D
la source

Réponses:

38

Vous pouvez utiliser le csvmodule Python .

Un exemple simple:

import csv
reader = csv.reader(open("test.csv", "r"))
for row in reader:
    for col in row:
        print col
dogbane
la source
Ma solution finale était en python car mon Perl était trop rouillé. Merci.
Steven D
2
Encore mieux, utilisez des pandas . Il est explicitement conçu pour fonctionner avec des données tabulaires.
Josh
38

Je suis probablement un peu trop tard, mais il existe un autre outil qui mérite d'être mentionné: csvkit

http://csvkit.readthedocs.org/

Il a beaucoup d'outils en ligne de commande qui peuvent:

  • reformatage de fichiers CSV,
  • convertir vers et à partir de CSV à partir de divers formats (JSON, SQL, XLS),
  • l'équivalent de cut, grep, sortet d' autres, mais CSV-conscient,
  • joindre différents fichiers CSV,
  • faire des requêtes SQL générales sur les données de fichiers CSV.
la romaia
la source
6
Un excellent outil qui répond à merveille aux critères de la question (en particulier, il ne nécessite pas de passer à un langage de programmation et est bien conçu pour s’adapter à d’autres utilitaires Unix).
mm2001
15

Cela ressemble à un travail pour Perl avec Text::CSV.

perl -MText::CSV -pe '
    BEGIN {$csv = Text::CSV->new();}
    $csv->parse($_) or die;
    @fields = $csv->fields();
    print @fields[1,3];
'

Voir la documentation pour savoir comment gérer les noms de colonnes. Le séparateur et le style de citation peuvent être ajustés avec les paramètres new. Voir aussi Text::CSV::Separatorpour deviner séparateur.

Gilles, arrête de faire le mal
la source
Existe-t-il un seul revêtement dans lequel vous pouvez compacter cela? J'aime perl, mais seulement lorsque je peux l'invoquer directement à partir de la ligne de commande plutôt qu'avec un script
Sridhar Sarnobat
2
@ user7000, à moins que votre shell ne soit (t)cshcette commande, cette commande fonctionnerait parfaitement à l'invite de votre shell. Vous pouvez toujours joindre ces lignes si vous le souhaitez sur une seule ligne. newline est généralement identique à l'espace dans la syntaxe perl, comme en C.
Stéphane Chazelas
Je suppose. Même si écraser plus de 2 lignes en 1 n’est pas ce que j’entends vraiment par une ligne. J'espérais qu'il y aurait un sucre syntaxique qui en ferait une partie implicitement (comme comment -ecréer une boucle implicite).
Sridhar Sarnobat
10

J'ai trouvé csvfix, un outil de ligne de commande fait bien son travail. Vous devrez toutefois le faire vous-même:

http://neilb.bitbucket.org/csvfix

Il fait tout ce que vous attendez, ordre / sélection des colonnes, scission / fusion et beaucoup de choses que vous ne voudriez pas générer d'insertions SQL à partir de données CSV et de données CSV différentes.

Daniel Burke
la source
8

Si vous souhaitez utiliser la ligne de commande (et ne créez pas un programme complet pour faire le travail), vous souhaitez utiliser des lignes , un projet sur lequel je travaille: c'est une interface de ligne de commande pour les données tabulaires, mais aussi une bibliothèque Python à utiliser dans vos programmes. Avec l’interface de ligne de commande, vous pouvez imprimer toutes les données au format CSV, XLS, XLSX, HTML ou n’importe quel autre format tabulaire pris en charge par la bibliothèque à l’aide d’une simple commande:

rows print myfile.csv

Si myfile.csvest comme ça:

state,city,inhabitants,area
RJ,Angra dos Reis,169511,825.09
RJ,Aperibé,10213,94.64
RJ,Araruama,112008,638.02
RJ,Areal,11423,110.92
RJ,Armação dos Búzios,27560,70.28

Ensuite, les lignes imprimeront le contenu de manière magnifique, comme ceci:

+-------+-------------------------------+-------------+---------+
| state |              city             | inhabitants |   area  |
+-------+-------------------------------+-------------+---------+
|    RJ |                Angra dos Reis |      169511 |  825.09 |
|    RJ |                       Aperibé |       10213 |   94.64 |
|    RJ |                      Araruama |      112008 |  638.02 |
|    RJ |                         Areal |       11423 |  110.92 |
|    RJ |            Armação dos Búzios |       27560 |   70.28 |
+-------+-------------------------------+-------------+---------+

L'installation

Si vous êtes un développeur Python et que vous êtes déjà pipinstallé sur votre ordinateur, exécutez-le simplement dans virtualenv ou avec sudo:

pip install rows

Si vous utilisez Debian:

sudo apt-get install rows

Autres fonctionnalités intéressantes

Conversion de formats

Vous pouvez convertir n'importe quel format pris en charge:

rows convert myfile.xlsx myfile.csv

Interrogation

Oui, vous pouvez utiliser SQL dans un fichier CSV:

$ rows query 'SELECT city, area FROM table1 WHERE inhabitants > 100000' myfile.csv
+----------------+--------+
|      city      |  area  |
+----------------+--------+
| Angra dos Reis | 825.09 |
|       Araruama | 638.02 |
+----------------+--------+

La conversion de la sortie de la requête en fichier au lieu de stdout est également possible à l'aide du --outputparamètre.

En tant que bibliothèque Python

Vous pouvez également utiliser vos programmes Python:

import rows
table = rows.import_from_csv('myfile.csv')
rows.export_to_txt(table, 'myfile.txt')
# `myfile.txt` will have same content as `rows print` output

Je espère que vous l'apprécierez!

Álvaro Justen
la source
6

R n’est pas mon langage de programmation préféré, mais c’est bon pour des choses comme celle-là. Si votre fichier csv est

***********
foo.csv
***********
 col1, col2, col3
"this, is the first entry", this is the second, 34.5
'some more', "messed up", stuff

À l'intérieur du type d'interprète R

> x=read.csv("foo.csv", header=FALSE)

> x
                     col1                col2   col3
1 this, is the first entry  this is the second   34.5
2              'some more'           messed up  stuff
> x[1]  # first col
                      col1
1 this, is the first entry
2              'some more'
> x[1,] # first row
                      col1                col2  col3
1 this, is the first entry  this is the second  34.5

En ce qui concerne vos autres demandes, pour "la possibilité de sélectionner des colonnes en fonction des noms de colonne indiqués dans la première ligne", voir

> x["col1"]
                      col1
1 this, is the first entry
2              'some more'

Pour "prise en charge d'autres styles de citation", voir l' quoteargument de read.csv (et les fonctions associées). Pour "prise en charge des fichiers séparés par des tabulations", voir l' separgument de read.csv (défini sepsur '\ t').

Pour plus d'informations, consultez l'aide en ligne.

> help(read.csv)
Faheem Mitha
la source
Je connais très bien R, mais mon objectif était d’obtenir quelque chose que je pourrais facilement utiliser de Bash.
Steven D
1
@Steven: R peut facilement être exécuté à partir de la ligne de commande, de la même manière que Python ou Perl, si c'est votre seule préoccupation. Voir Rscript(partie de la distribution de base R) ou le paquet addon littler. Vous pouvez faire #!/usr/bin/env Rscriptou similaire.
Faheem Mitha
Ah oui. Je connais assez bien R, mais je ne l’ai pas beaucoup utilisé pour créer ce type d’utilitaire. Quelque chose fonctionne en Python, mais je peux aussi essayer de créer quelque chose en R.
Steven D
4

Miller est un autre outil intéressant pour manipuler des données nominatives, y compris CSV (avec en-têtes). Pour extraire la première colonne d’un fichier CSV, sans vous soucier de son nom, vous feriez quelque chose comme:

printf '"first,column",second,third\n1,2,3\n' |
  mlr --csv --implicit-csv-header --headerless-csv-output cut -f 1
Stephen Kitt
la source
Miller est très impressionnant. Je le comparerais à awk, mais très sensible à DSV.
Derek Mahar
3

Ou, vous pouvez essayer un peu de magie awk . Cependant, je ne suis pas un bon utilisateur awk et je ne peux pas confirmer que cela fonctionnerait correctement et comment le faire.

rvs
la source
9
Voici un awk CSV Parser que j’avais utilisé il ya quelque temps .. Il semble assez bien pensé ... lorance.freeshell.org/csv
Peter.O
2

Pour utiliser python à partir de la ligne de commande, vous pouvez consulter pythonpy ( https://github.com/Russell91/pythonpy ):

$ echo $'a,b,c\nd,e,f' | py '[x[1] for x in csv.reader(sys.stdin)']
b
e
RussellStewart
la source
2

essayez "csvtool" ce paquet, c'est un outil pratique en ligne de commande pour gérer les fichiers CSV

dominic
la source
1
Déjà mentionné, avec plus de détails ...
jasonwryan
2

Cissy fera également le traitement CSV en ligne de commande. Il est écrit en C (petit / léger) avec les paquets rpm et deb disponibles pour la plupart des distributions.

En utilisant l'exemple:

echo '"this, is the first entry", this is the second, 34.5' | cissy -c 1
"this, is the first entry"

ou

echo '"this, is the first entry", this is the second, 34.5' | cissy -c 2
 this is the second

ou

echo '"this, is the first entry", this is the second, 34.5' | cissy -c 2-
 this is the second, 34.5
slass100
la source
1

Il existe également une bibliothèque Curry pour lire / écrire des fichiers au format CSV : CSV .

imz - Ivan Zakharyaschev
la source
2
Souhaitez-vous poster un exemple de code, comme les réponses Perl, Python et R? (Surtout que Curry n'est pas un langage de script Unix commun.)
Gilles 'SO, arrête de faire le mal'
@ Gilles: Oui, vous avez raison, je devrais publier un exemple de code pour améliorer la réponse. Je vais faire ça dans un moment.
imz - Ivan Zakharyaschev
1

Miller ( http://johnkerl.org/miller/doc/index.html ) est l'un des meilleurs outils . Cela ressemble à awk, sed, couper, joindre et trier des données indexées telles que CSV, TSV et JSON tabulaire.

Par exemple

echo '"this, is the first entry", this is the second, 34.5' | \
mlr --icsv --implicit-csv-header cat

vous donne

1=this, is the first entry,2= this is the second,3= 34.5

Si vous voulez un TSV

echo '"this, is the first entry", this is the second, 34.5' | \
mlr --c2t --implicit-csv-header cat

vous donne (il est possible de supprimer l'en-tête)

1       2       3
this, is the first entry         this is the second      34.5

Si vous voulez la première et la troisième colonne, changer leur ordre

echo '"this, is the first entry", this is the second, 34.5' | \
mlr --csv --implicit-csv-header --headerless-csv-output cut -o -f 3,1

vous donne

 34.5,"this, is the first entry"
Aborruso
la source
1

Si vous voulez un outil visuel / interactif dans le terminal, je recommande vivement VisiData.

entrez la description de l'image ici

Il contient des tableaux de fréquences (voir ci-dessus), des tableaux de points de fusion, des diagrammes de dispersion, des filtres / calculs utilisant Python, etc.

Vous pouvez transmettre des fichiers CSV comme si

vd hello.csv

Il y a des options spécifiques csv: --csv-dialect, --csv-delimiter, --csv-quotecharet --csv-skipinitialspacepour l' écoute fine gestion des fichiers csv.

DameDebugger
la source
0

Une solution awk

awk -vq='"' '
func csv2del(n) {
  for(i=n; i<=c; i++)
    {if(i%2 == 1) gsub(/,/, OFS, a[i])
    else a[i] = (q a[i] q)
    out = (out) ? out a[i] : a[i]}
  return out}
{c=split($0, a, q); out=X;
  if(a[1]) $0=csv2del(1)
  else $0=csv2del(2)}1' OFS='|' file
Srini
la source