Esiste un robusto strumento da riga di comando per l'elaborazione di file CSV?


47

Lavoro con file CSV e a volte ho bisogno di controllare rapidamente il contenuto di una riga o colonna dalla riga di comando. In molti casi cut, head, tail, e gli amici farà il lavoro; tuttavia, il taglio non può facilmente gestire situazioni come

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

Qui, la prima virgola fa parte del primo campo, ma cut -d, -f1non è d'accordo. Prima di scrivere una soluzione da solo, mi chiedevo se qualcuno sapesse di un buon strumento che già esiste per questo lavoro. Dovrebbe, almeno, essere in grado di gestire l'esempio sopra e restituire una colonna da un file in formato CSV. Altre caratteristiche desiderabili includono la possibilità di selezionare colonne in base ai nomi delle colonne indicati nella prima riga, supporto per altri stili di quotazione e supporto per file separati da tabulazioni.

Se non conosci questo strumento ma hai suggerimenti sull'implementazione di un tale programma in Bash, Perl o Python, o in altri linguaggi di scripting comuni, non mi dispiacerebbe tali suggerimenti.

Risposte:


38

Puoi usare il csvmodulo di Python .

Un semplice esempio:

import csv
reader = csv.reader(open("test.csv", "r"))
for row in reader:
    for col in row:
        print col

La mia soluzione finale era in pitone poiché il mio Perl era troppo arrugginito. Grazie.
Steven D,

2
Ancora meglio, usa i panda . È esplicitamente progettato per funzionare con dati tabulari.
Josh,

38

Probabilmente sono un po 'troppo tardi, ma c'è un altro strumento degno di nota: csvkit

http://csvkit.readthedocs.org/

Ha molti strumenti da riga di comando che possono:

  • riformattazione di file CSV,
  • convertire da e verso CSV da vari formati (JSON, SQL, XLS),
  • l'equivalente di cut, grep, sorte altri, ma CSV-aware,
  • unire file CSV diversi,
  • eseguire query SQL generali sui dati dai file CSV.

6
Uno strumento eccellente che soddisfa meravigliosamente i criteri della domanda (in particolare non richiede di saltare in un linguaggio di programmazione ed è ben realizzato per adattarsi ad altre utility Unix).
mm2001

15

Sembra un lavoro con Perl Text::CSV.

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

Consulta la documentazione per come gestire i nomi delle colonne. Il separatore e lo stile di quotazione possono essere regolati con parametri su new. Vedi anche Text::CSV::Separatorper indovinare il separatore.


C'è un solo rivestimento in cui puoi compattarlo. Mi piace il perl, ma solo quando posso invocarlo direttamente dalla riga di comando piuttosto che con una sceneggiatura
Sridhar Sarnobat,

2
@ user7000, a meno che la tua shell non sia (t)cshquel comando funzionerebbe bene al prompt della tua shell. Puoi sempre unire quelle linee se vuoi su una linea. newline è generalmente come lo spazio nella sintassi del perl come in C.
Stéphane Chazelas,

Suppongo. Anche se schiacciare più di 2 righe in 1 non è ciò che intendo veramente per un liner. Speravo che ci fosse un po 'di zucchero sintattico che lo avrebbe fatto implicitamente (come il modo in cui -ecrea un ciclo implicito).
Sridhar Sarnobat,

10

Ho trovato csvfix, uno strumento da riga di comando fa bene il lavoro. Dovrai farlo tu stesso comunque:

http://neilb.bitbucket.org/csvfix

Fa tutto ciò che ti aspetteresti, ordina / seleziona colonne, dividi / unisci e molti non ti piacerebbe generare inserti SQL da dati CSV e diffondere dati CSV.


8

Se vuoi usare la riga di comando (e non creare un intero programma per fare il lavoro), ti piacerebbe usare le righe , un progetto su cui sto lavorando: è un'interfaccia della riga di comando per i dati tabulari ma anche una libreria Python da usare nei tuoi programmi. Con l'interfaccia della riga di comando puoi stampare in modo carino tutti i dati in CSV, XLS, XLSX, HTML o qualsiasi altro formato tabulare supportato dalla libreria con un semplice comando:

rows print myfile.csv

Se myfile.csvè così:

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

Quindi le righe stamperanno i contenuti in modo meraviglioso, in questo modo:

+-------+-------------------------------+-------------+---------+
| 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 |
+-------+-------------------------------+-------------+---------+

Installazione

Se sei uno sviluppatore Python e hai già pipinstallato sul tuo computer, esegui un virtualenv o con sudo:

pip install rows

Se stai usando Debian:

sudo apt-get install rows

Altre caratteristiche interessanti

Conversione di formati

Puoi convertire tra qualsiasi formato supportato:

rows convert myfile.xlsx myfile.csv

Interrogazione

Sì, puoi usare SQL in un file CSV:

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

È anche possibile convertire l'output della query in un file anziché in stdout utilizzando il --outputparametro

Come libreria Python

Puoi farlo anche nei tuoi programmi 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

Spero ti sia piaciuto!


6

R non è il mio linguaggio di programmazione preferito, ma è buono per cose come questa. Se il tuo file CSV è

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

All'interno del tipo di interprete 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

Per quanto riguarda le altre tue richieste, per "la possibilità di selezionare le colonne in base ai nomi delle colonne indicati nella prima riga" vedi

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

Per "supporto per altri stili di quotazione", consultare l' quoteargomento read.csv (e le relative funzioni). Per "supporto per file separati da tabulazione" consultare l' separgomento to read.csv (impostato sepsu '\ t').

Per ulteriori informazioni, consultare la guida in linea.

> help(read.csv)

Conosco molto bene R, ma il mio obiettivo era avere qualcosa che potevo usare facilmente da Bash.
Steven D,

1
@Steven: R può essere facilmente eseguito dalla riga di comando, allo stesso modo di Python o Perl, se questa è la tua unica preoccupazione. Vedi Rscript(parte della distribuzione R di base) o il pacchetto di componenti aggiuntivi littler. Puoi fare #!/usr/bin/env Rscripto simili.
Faheem Mitha,

Ah sì. Sono abbastanza abile in R ma non l'ho usato molto per creare questo tipo di utilità. Ho qualcosa che funziona in Python ma potrei provare a creare qualcosa anche in R.
Steven D


4

Miller è un altro strumento utile per manipolare i dati basati sul nome, incluso CSV (con intestazioni). Per estrarre la prima colonna di un file CSV, senza preoccuparti del suo nome, dovresti fare qualcosa del genere

printf '"first,column",second,third\n1,2,3\n' |
  mlr --csv --implicit-csv-header --headerless-csv-output cut -f 1

Miller è davvero impressionante. Lo paragonerei a awk, ma altamente consapevole di DSV.
Derek Mahar,

3

Oppure, si potrebbe provare qualche awk magia. Tuttavia, non sono un buon utente awk e non posso confermare che funzionerebbe correttamente e come farlo.


9
Ecco un parser CSV Parser che ho usato un po 'di tempo fa. Sembra abbastanza ben pensato ... lorance.freeshell.org/csv
Peter.O



2

prova "csvtool" questo pacchetto è un utile strumento da riga di comando per la gestione dei file CSV


1
Già menzionato, con maggiori dettagli ...
Jasonwryan,

2

cissy eseguirà anche l'elaborazione csv da riga di comando. È scritto in C (piccolo / leggero) con pacchetti rpm e deb disponibili per la maggior parte delle distribuzioni.

Utilizzando l'esempio:

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

o

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

o

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




1

Uno dei migliori strumenti è Miller ( http://johnkerl.org/miller/doc/index.html ). È come awk, sed, cut, join e sort per dati indicizzati come CSV, TSV e JSON tabulare.

Per esempio

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

ti dà

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

Se vuoi un TSV

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

ti dà (è possibile rimuovere l'intestazione)

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

Se vuoi prima e terza colonna, cambiando il loro ordine

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

ti dà

 34.5,"this, is the first entry"

1

Se vuoi uno strumento visivo / interattivo nel terminale, consiglio vivamente VisiData.

inserisci qui la descrizione dell'immagine

Ha tabelle di frequenza (mostrate sopra), pivot, fusione, grafici a dispersione, filtro / calcolo usando Python e altro.

Puoi passare file CSV in questo modo

vd hello.csv

Ci sono opzioni specifiche CSV: --csv-dialect, --csv-delimiter, --csv-quotechar, e --csv-skipinitialspaceper la messa a punto la gestione di file CSV.


0

Una soluzione terribile

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.