¿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

Respuestas:


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

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


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

¿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.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.