¿Existe una utilidad de línea de comandos para transponer un archivo csv?

16

Dado un archivo así

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

¿Existe una utilidad de línea de comandos para transponer el contenido de modo que la salida aparezca así?

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

Respuestas:

6
ruby -rcsv -e 'puts CSV.parse(STDIN).transpose.map &:to_csv' < in.csv > out.csv
luikore
fuente
Dada la antigüedad de esta pregunta, justificaré mi cambio a esto como aceptado: a) Esta respuesta es mucho más sucinta que la de Gilles python, b) rubyno es menos portátil que python, yc) esto también muestra cómo pasar la entrada / salida archivos. Bravo @luikore, y bienvenidos a Unix y Linux. Por favor, quédate.
Cory Klein
una advertencia, en el csv, los campos deben ser citados
yosefrow
@yosefrow No es necesario citar. Probé el comando antes de publicar esta respuesta.
luikore
ok debería haber dicho "mayo" entonces. No funcionó para mí hasta que cité todos los campos. Podría tener que ver con mi contenido de datos
yosefrow
16

El análisis CSV no se realiza fácilmente solo con las herramientas POSIX, a menos que esté utilizando una variante CSV simplificada sin comillas (de modo que las comas no puedan aparecer en un campo). Incluso entonces, esta tarea no parece fácil de hacer con awk u otro procesamiento de texto a herramienta. Puede usar Perl con Text::CSV, Python con csv, R con read.csv, Ruby con CSV , ... (Todos estos son parte de la biblioteca estándar del idioma respectivo, excepto Perl).

Por ejemplo, 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])
Gilles 'SO- deja de ser malvado'
fuente
11

Desde /programming//a/2776078 :

$ apt-get install csvtool

Y luego convertir

$ csvtool transpose input.csv > ouput.csv

O en la tubería

$ ... | csvtool transpose - | ...
Grzegorz Wierzowiecki
fuente
1
hermosa. Solo ... | csvtranspose | ...superaría eso, en cuanto a sintaxis.
masterxilo
3

Una solución de rápida y sucia :

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
fuente
¿Qué representa / tmp / l? Además, ¿no sería más sencillo colocar a través de las columnas en lugar de líneas, algo a lo largo de las líneasfor ((i=1; i<=$num_cols; ++i)); do paste -s -d, <(cut -f$i -d, file.txt); done
Iruvar
Tenga en cuenta que esto funciona para la entrada de OP, pero solo porque sus datos tienen el mismo número de filas y columnas, que generalmente no es el caso.
tokland
csv tiene especificación relativa a las cotizaciones dpuble, es decir, this "is" examplela célula está codificada "this ""is"" example"No estoy convencido si se encarga de esta solución tan adecuadamente los casos
Grzegorz Wierzowiecki
0

Dada la limitación sugerida (sin comillas, sin comas incrustadas), es simple en awk (ya que sería en perl sin tener en cuenta más de mil líneas en CSV.pm, 2300 líneas en csv.rb- python tiene solo 450 líneas csv.py).

Aquí hay un ejemplo para 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];
    }
}

Por cierto: el ejemplo dado tenía espacio adicional que OP asumió que sería eliminado; los otros ejemplos no abordaron este detalle.

Thomas Dickey
fuente