Existe um utilitário de linha de comando para transpor um arquivo csv?

16

Dado um arquivo como esse

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

Existe um utilitário de linha de comando para transpor o conteúdo para que a saída apareça assim

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

Respostas:

6
ruby -rcsv -e 'puts CSV.parse(STDIN).transpose.map &:to_csv' < in.csv > out.csv
luikore
fonte
Dada a idade desta pergunta, justificarei minha mudança para a seguinte: a) Essa resposta é muito mais sucinta que a de Gilles python, b) rubynão é menos portátil do que pythonec) mostra também como passar a entrada / saída arquivos. Bravo @luikore, e bem-vindo ao Unix e Linux. Por favor, fique por aqui.
Cory Klein
uma ressalva, no csv, os campos devem ser citados
yosefrow
@yosefrow Não há necessidade de citar. Testei o comando antes de postar esta resposta.
luikore
ok deveria ter dito "pode" então. Não funcionou para mim até que eu citei todos os campos. Pode ter a ver com o conteúdo dos meus dados
yosefrow
16

A análise de CSV não é feita facilmente apenas com as ferramentas POSIX, a menos que você esteja usando uma variante simplificada de CSV sem aspas (para que vírgulas não possam aparecer em um campo). Mesmo assim, essa tarefa não parece fácil de ser feita com o awk ou outro processamento de texto na ferramenta. Você pode usar Perl com Text::CSV, Python com csv, R com read.csv, Ruby com CSV ,… (Tudo isso faz parte da biblioteca padrão da respectiva linguagem, exceto Perl.)

Por exemplo, em 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- parar de ser mau'
fonte
11

Em /programming//a/2776078 :

$ apt-get install csvtool

E depois converter

$ csvtool transpose input.csv > ouput.csv

Ou no pipeline

$ ... | csvtool transpose - | ...
Grzegorz Wierzowiecki
fonte
1
lindo. Só ... | csvtranspose | ...iria superar isso, em termos de sintaxe.
masterxilo
3

Uma solução rápida e suja do :

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
fonte
o que representa / tmp / l? Além disso, não seria mais simples para percorrer as colunas em vez de linhas, algo ao longo das linhas defor ((i=1; i<=$num_cols; ++i)); do paste -s -d, <(cut -f$i -d, file.txt); done
Iruvar
Observe que isso funciona para a entrada do OP, mas apenas porque seus dados têm o mesmo número de linhas e colunas, o que geralmente não é o caso.
tokland
csv tem especificação sobre citações dpuble, ie this "is" examplecelular é codificado "this ""is"" example"Não estou convencido se esta solução alças tais casos corretamente
Grzegorz Wierzowiecki
0

Dada a limitação sugerida (sem citação, sem vírgulas incorporadas), é simples no awk (como seria em perl, não levando em conta mais de mil linhas em CSV.pm, 2300 linhas em csv.rb- python tem apenas 450 linhas em csv.py).

Aqui está um exemplo para o 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];
    }
}

A propósito: o exemplo dado tinha espaço extra que o OP assumiu que seria removido; os outros exemplos não abordaram esse detalhe.

Thomas Dickey
fonte