Gibt es ein robustes Befehlszeilentool für die Verarbeitung von CSV-Dateien?

47

Ich arbeite mit CSV-Dateien und muss manchmal schnell den Inhalt einer Zeile oder Spalte über die Befehlszeile überprüfen. In vielen Fällen cut, head, tail, und Freunde werden die Arbeit erledigen; Schnitt kann jedoch nicht leicht mit Situationen umgehen wie

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

Hier ist das erste Komma Teil des ersten Feldes, cut -d, -f1stimmt aber nicht überein. Bevor ich selbst eine Lösung schrieb, fragte ich mich, ob jemand von einem guten Werkzeug wusste, das es für diesen Job bereits gibt. Zumindest muss es in der Lage sein, mit dem obigen Beispiel umzugehen und eine Spalte aus einer CSV-formatierten Datei zurückzugeben. Weitere wünschenswerte Funktionen sind die Möglichkeit, Spalten basierend auf den in der ersten Zeile angegebenen Spaltennamen auszuwählen, Unterstützung für andere Anführungszeichenstile und Unterstützung für durch Tabulatoren getrennte Dateien.

Wenn Sie kein solches Tool kennen, aber Vorschläge zur Implementierung eines solchen Programms in Bash, Perl oder Python oder anderen gängigen Skriptsprachen haben, stören mich solche Vorschläge nicht.

Steven D
quelle

Antworten:

38

Sie können das Python- csvModul verwenden.

Ein einfaches Beispiel:

import csv
reader = csv.reader(open("test.csv", "r"))
for row in reader:
    for col in row:
        print col
Dogbane
quelle
Meine endgültige Lösung war in Python, da mein Perl zu rostig war. Vielen Dank.
Steven D
2
Noch besser, benutze Pandas . Es wurde explizit für die Arbeit mit Tabellendaten entwickelt.
Josh
38

Ich bin wahrscheinlich ein bisschen zu spät, aber es gibt noch ein anderes erwähnenswertes Tool: csvkit

http://csvkit.readthedocs.org/

Es hat eine Menge Kommandozeilen-Tools, die:

  • Neuformatierung von CSV-Dateien,
  • Konvertieren von und nach CSV aus verschiedenen Formaten (JSON, SQL, XLS),
  • das Äquivalent von cut, grep, sortund andere, aber CSV-aware,
  • verschiedene CSV-Dateien zusammenfügen,
  • Führen Sie allgemeine SQL-Abfragen für Daten aus CSV-Dateien durch.
Romaia
quelle
6
Ein exzellentes Tool, das die Fragestellungen hervorragend erfüllt (insbesondere erfordert es keinen Sprung in eine Programmiersprache und ist gut auf andere Unix-Dienstprogramme abgestimmt).
mm2001
15

Klingt nach einem Job für Perl mit Text::CSV.

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

Informationen zum Umgang mit Spaltennamen finden Sie in der Dokumentation. Das Trennzeichen und der Anführungsstil können mit den Parametern auf eingestellt werden new. Siehe auch Text::CSV::Separatorzum Erraten von Trennzeichen.

Gilles 'SO - hör auf böse zu sein'
quelle
Gibt es eine Einzeiler, in die Sie diese komprimieren können? Ich mag Perl, aber nur, wenn ich es direkt von der Kommandozeile aus aufrufen kann und nicht mit einem Skript
Sridhar Sarnobat
2
@ user7000, es sei denn, Ihr Shell- (t)cshBefehl funktioniert einwandfrei an der Eingabeaufforderung Ihrer Shell. Sie können diese Zeilen jederzeit miteinander verbinden, wenn Sie dies in einer Zeile möchten. Newline ist im Allgemeinen genau wie Leerzeichen in der Perl-Syntax wie in C.
Stéphane Chazelas
Ich vermute. Obwohl ich mit einem Einzeiler nicht wirklich meine, mehr als zwei Zeilen in eine zu quetschen. Ich hatte gehofft, es gäbe einen syntaktischen Zucker, der einen Teil davon implizit ausführen würde (zum Beispiel, wie das -eeine implizite Schleife erzeugt).
Sridhar Sarnobat
10

Ich habe csvfix gefunden, ein Befehlszeilentool erledigt die Arbeit gut. Sie müssen es jedoch selbst machen:

http://neilb.bitbucket.org/csvfix

Es erledigt alles, was Sie erwarten, sortiert / wählt Spalten aus, teilt / führt zusammen und viele, die Sie nicht gerne aus CSV-Daten und unterschiedlichen CSV-Daten SQL-Einfügungen generieren würden.

Daniel Burke
quelle
8

Wenn Sie die Befehlszeile verwenden möchten (und kein komplettes Programm erstellen möchten), möchten Sie Zeilen verwenden , ein Projekt, an dem ich arbeite: Es ist eine Befehlszeilenschnittstelle für tabellarische Daten, aber auch eine Python-Bibliothek, die Sie in Ihren Programmen verwenden können. Über die Befehlszeilenschnittstelle können Sie alle Daten in CSV, XLS, XLSX, HTML oder einem anderen von der Bibliothek unterstützten Tabellenformat mit einem einfachen Befehl hübsch ausdrucken:

rows print myfile.csv

Wenn das so myfile.csvist:

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

Dann drucken die Zeilen den Inhalt auf eine schöne Art und Weise:

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

Installieren

Wenn Sie ein Python-Entwickler sind und bereits pipauf Ihrem Computer installiert sind, starten Sie einfach in einer virtuellen Umgebung oder mit sudo:

pip install rows

Wenn Sie Debian verwenden:

sudo apt-get install rows

Andere coole Funktionen

Formate konvertieren

Sie können zwischen allen unterstützten Formaten konvertieren:

rows convert myfile.xlsx myfile.csv

Abfragen

Ja, Sie können SQL in eine CSV-Datei einfügen:

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

Über den --outputParameter ist es auch möglich, die Ausgabe der Abfrage in eine Datei anstelle von stdout zu konvertieren .

Als Python-Bibliothek

Sie können Sie in Ihren Python-Programmen auch:

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

Hoffe es gefällt euch!

Álvaro Justen
quelle
6

R ist nicht meine Lieblingsprogrammiersprache, aber es ist gut für solche Dinge. Wenn Ihre CSV-Datei ist

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

Innerhalb des R-Interpreter-Typs

> 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

In Bezug auf Ihre anderen Anforderungen finden Sie unter "Die Möglichkeit, Spalten basierend auf den in der ersten Zeile angegebenen Spaltennamen auszuwählen"

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

Für "Unterstützung für andere quoteAnführungszeichen " siehe das Argument zu read.csv (und verwandte Funktionen). sepInformationen sepzur "Unterstützung von durch Tabulatoren getrennten Dateien" finden Sie im Argument "read.csv" ( auf "\ t" gesetzt).

Weitere Informationen finden Sie in der Online-Hilfe.

> help(read.csv)
Faheem Mitha
quelle
Ich kenne R sehr gut, aber mein Ziel war es, etwas zu haben, das ich von Bash leicht gebrauchen kann.
Steven D
1
@Steven: R kann genauso wie Python oder Perl problemlos über die Befehlszeile ausgeführt werden, wenn dies Ihr einziges Problem ist. Siehe Rscript(Teil der Basis-R-Distribution) oder das Addon-Paket littler. Sie können #!/usr/bin/env Rscriptoder ähnliches tun .
Faheem Mitha
Ah ja. Ich beherrsche R ziemlich gut, habe es aber nicht viel benutzt, um diese Art von Dienstprogramm zu erstellen. Ich habe etwas in Python am Laufen, aber ich kann auch versuchen, etwas in R zu erstellen.
Steven D
4

Miller ist ein weiteres nützliches Tool zum Bearbeiten von namensbasierten Daten, einschließlich CSV (mit Überschriften). Wenn Sie die erste Spalte einer CSV-Datei extrahieren möchten, ohne sich um den Namen zu kümmern, müssen Sie Folgendes tun

printf '"first,column",second,third\n1,2,3\n' |
  mlr --csv --implicit-csv-header --headerless-csv-output cut -f 1
Stephen Kitt
quelle
Miller ist sehr beeindruckend. Ich würde es mit vergleichen awk, aber sehr DSV-fähig.
Derek Mahar
3

Oder Sie könnten etwas Awk- Magie ausprobieren . Allerdings bin ich kein guter awk-Benutzer und kann nicht bestätigen, dass dies richtig funktioniert, und wie es geht.

Wohnmobile
quelle
9
Hier ist ein awk CSV-Parser, den ich vor einiger
Peter.O
2

Um Python über die Befehlszeile zu verwenden, können Sie Pythonpy auschecken ( 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
quelle
2

versuchen Sie "csvtool" dieses Pakets, es ist ein praktisches Kommandozeilen-Tool für den Umgang mit CSV-Dateien

dominierend
quelle
1
Bereits erwähnt, mit mehr Details ...
Jasonwryan
2

cissy führt auch die Befehlszeilen-CSV-Verarbeitung durch. Es ist in C (klein / leicht) mit RPM- und Deb-Paketen geschrieben, die für die meisten Distributionen verfügbar sind.

Mit dem Beispiel:

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

oder

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

oder

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

Es gibt auch eine Curry- Bibliothek zum Lesen / Schreiben von Dateien im CSV-Format: CSV .

imz - Ivan Zakharyaschev
quelle
2
Würde es Ihnen etwas ausmachen, Beispielcode wie die Antworten in Perl, Python und R zu veröffentlichen? (Zumal Curry keine verbreitete Unix-Skriptsprache ist.)
Gilles 'SO - hör auf, böse zu sein',
@Gilles: Ja, Sie haben recht, ich sollte einen Beispielcode posten, um die Antwort zu verbessern. Ich mache das gleich.
imz - Ivan Zakharyaschev
1

Das Github Repo Structured Text Tools verfügt über eine nützliche Liste der relevanten Linux-Befehlszeilen-Tools. Im Abschnitt "Durch Trennzeichen getrennte Werte " sind mehrere CSV-fähige Tools aufgeführt, die die angeforderten Vorgänge direkt unterstützen.

JonDeg
quelle
1

Eines der besten Tools ist Miller ( http://johnkerl.org/miller/doc/index.html ). Es ist wie awk, sed, cut, join und sort für mit Namen indizierte Daten wie CSV, TSV und tabellarisches JSON.

Zum Beispiel

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

gibt Ihnen

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

Wenn Sie einen TSV wollen

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

gibt Ihnen (es ist möglich, den Header zu entfernen)

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

Wenn Sie die erste und dritte Spalte möchten, ändern Sie deren Reihenfolge

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

gibt Ihnen

 34.5,"this, is the first entry"
Aborruso
quelle
1

Wenn Sie ein visuelles / interaktives Tool im Terminal wünschen, empfehle ich VisiData von ganzem Herzen.

Bildbeschreibung hier eingeben

Es verfügt über Frequenztabellen (siehe oben), Pivot, Schmelzen, Streudiagramme, Filtern / Berechnen mit Python und mehr.

Sie können csv-Dateien so übergeben

vd hello.csv

Es gibt csv spezifische Optionen: --csv-dialect, --csv-delimiter, --csv-quotechar, und --csv-skipinitialspacefür die Feinabstimmung von csv - Dateien verarbeitet werden .

DameDebugger
quelle
0

Eine gute Lösung

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
quelle