Existe-t-il un utilitaire de ligne de commande pour transposer un fichier csv?


16

Étant donné un fichier comme ça

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

Existe-t-il un utilitaire de ligne de commande pour transposer le contenu afin que la sortie apparaisse comme telle

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

Réponses:


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

Compte tenu de l'âge de cette question, je justifierai mon passage à celui-ci comme étant accepté: a) Cette réponse est beaucoup plus succincte que celle de Gilles python, b) rubyn'est pas moins portable que python, et c) cela montre également comment passer les entrées / sorties des dossiers. Bravo @luikore, et bienvenue sur Unix et Linux. Veuillez rester.
Cory Klein

une mise en garde, dans le csv, les champs doivent être cités
yosefrow

@yosefrow Pas besoin de citer. J'ai testé la commande avant de poster cette réponse.
luikore

ok aurait dû dire "peut" alors. Cela n'a pas fonctionné pour moi jusqu'à ce que je cite tous les champs. Pourrait avoir à voir avec mon contenu de données
yosefrow

16

L'analyse CSV n'est pas facile à faire avec les outils POSIX uniquement, sauf si vous utilisez une variante CSV simplifiée sans guillemets (de sorte que les virgules ne puissent pas apparaître dans un champ). Même alors, cette tâche ne semble pas facile à faire avec un outil de traitement de texte ou un autre outil. Vous pouvez utiliser Perl avec Text::CSV, Python avec csv, R avec read.csv, Ruby avec CSV ,… (Tous ces éléments font partie de la bibliothèque standard du langage respectif à l'exception de Perl.)

Par exemple, en 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

Une solution rapide et sale :

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

que représente / tmp / l? De plus, ne serait-il pas plus simple de parcourir les colonnes plutôt que les lignes, quelque chose le long des lignes defor ((i=1; i<=$num_cols; ++i)); do paste -s -d, <(cut -f$i -d, file.txt); done
iruvar

Notez que cela fonctionne pour l'entrée OP, mais uniquement parce que leurs données ont le même nombre de lignes et de colonnes, ce qui n'est généralement pas le cas.
Tokland

csv a des spécifications concernant les guillemets doubles, c'est- this "is" exampleà- dire que la cellule est encodée "this ""is"" example"Je ne suis pas convaincu si cette solution gère correctement ces cas
Grzegorz Wierzowiecki

0

Compte tenu de la limitation suggérée (pas de guillemets, pas de virgules imbriquées), c'est simple en awk (comme ce serait en perl sans prendre en compte plus de mille lignes en CSV.pm, 2300 lignes en csv.rb- python n'a que 450 lignes csv.py).

Voici un exemple pour 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];
    }
}

Soit dit en passant: l'exemple donné avait de l'espace supplémentaire que OP supposait être supprimé; les autres exemples n'ont pas abordé ce détail.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.