Gibt es ein Kommandozeilenprogramm, um eine CSV-Datei zu transponieren?

16

Bei einer Datei wie dieser

First,Last,Age
Cory,Klein,27
John Jacob,Smith,30

Gibt es ein Befehlszeilenprogramm, um den Inhalt so zu transponieren, dass die Ausgabe so aussieht?

First,Cory,John Jacob
Last,Klein,Smith
Age,27,30
Cory Klein
quelle

Antworten:

6
ruby -rcsv -e 'puts CSV.parse(STDIN).transpose.map &:to_csv' < in.csv > out.csv
luikore
quelle
Angesichts des Alters dieser Frage werde ich meine Änderung als akzeptiert begründen: a) Diese Antwort ist viel prägnanter als die von Gilles python, b) rubyist nicht weniger portabel als pythonund c) zeigt auch, wie die Eingabe / Ausgabe übergeben wird Dateien. Bravo @luikore und willkommen bei Unix & Linux. Bitte bleiben Sie dabei.
Cory Klein
eine Einschränkung, in der CSV, Felder müssen zitiert werden
Yosefrow
@yosefrow Keine Notwendigkeit zu zitieren. Ich habe den Befehl getestet, bevor ich diese Antwort gepostet habe.
luikore vor
16

CSV-Analyse ist nur mit POSIX-Tools nicht einfach durchzuführen, es sei denn, Sie verwenden eine vereinfachte CSV-Variante ohne Anführungszeichen (sodass in einem Feld keine Kommas angezeigt werden können). Selbst dann scheint es nicht einfach zu sein, diese Aufgabe mit awk oder einer anderen Textverarbeitung zu erledigen. Sie können Perl mit Text::CSV, Python mit csv, R mit read.csv, Ruby mit CSV , ... verwenden. (Alle diese sind Teil der Standardbibliothek der jeweiligen Sprache mit Ausnahme von Perl.)

Zum Beispiel in Python:

import csv, sys
rows = list(csv.reader(sys.stdin))
writer = csv.writer(sys.stdout)
for col in xrange(0, len(rows[0])):
    writer.writerow([row[col] for row in rows])
Gilles 'SO - hör auf böse zu sein'
quelle
11

Von /programming//a/2776078 :

$ apt-get install csvtool

Und dann konvertieren

$ csvtool transpose input.csv > ouput.csv

Oder in der Pipeline

$ ... | csvtool transpose - | ...
Grzegorz Wierzowiecki
quelle
1
schön. Das ... | csvtranspose | ...würde nur die Syntax übertreffen.
Masterxilo
3

Eine schnelle und schmutzige Lösung:

c=1
file=file.txt
num_lines=$(wc -l < "$file")

for ((i=0; i<num_lines; i++)) {
    cut -d, -f$c "$file" | paste -sd ','
    ((c++))
}
Gilles Quenot
quelle
Was bedeutet / tmp / l? for ((i=1; i<=$num_cols; ++i)); do paste -s -d, <(cut -f$i -d, file.txt); done
Wäre
Beachten Sie, dass dies für die OP-Eingabe funktioniert, jedoch nur, weil deren Daten dieselbe Anzahl von Zeilen und Spalten aufweisen, was normalerweise nicht der Fall ist.
Tokland
CSV hat Spezifikation in Bezug auf dpuble Anführungszeichen, dh this "is" exampleZelle ist codiert "this ""is"" example"Ich bin nicht überzeugt, ob diese Lösung solche Fälle ordnungsgemäß behandelt
Grzegorz Wierzowiecki
0

In Anbetracht der vorgeschlagenen Einschränkung (keine Anführungszeichen, keine eingebetteten Kommas) ist es in awk einfach (wie es in Perl ohne Berücksichtigung von mehr als tausend Zeilen in wäre CSV.pm, 2300 Zeilen in csv.rb- Python hat nur 450 Zeilen in csv.py).

Hier ist ein Beispiel für awk:

#!/usr/bin/awk -f
BEGIN { width=0; }
{
    max = split($0, list, ",");
    # printf "%d:%s\n", NR, $0;
    if (width < max)
        width = max;
    for (n = 1; n <= max; ++n) {
        sub("^[     ]*","",list[n]);
        sub("[  ]*$","",list[n]);
        # printf "\t%d:%s\n", n, list[n];
        if ( columns[n] != "" ) {
            columns[n] = columns[n] ", ";
        }
        columns[n] = columns[n] list[n];
    }
}
END {
    # printf "%d columns\n", width;
    for (n = 1; n <= width; ++n) {
        printf "%s\n", columns[n];
    }
}

Übrigens: Das angegebene Beispiel hatte zusätzlichen Platz, von dem OP annahm, dass er entfernt werden würde. Die anderen Beispiele haben dieses Detail nicht angesprochen.

Thomas Dickey
quelle