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

Antworten:


6
ruby -rcsv -e 'puts CSV.parse(STDIN).transpose.map &:to_csv' < in.csv > out.csv

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])


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

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.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.