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

Respostas:


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

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


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

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.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.