Apakah ada utilitas baris perintah untuk memindahkan file csv?

16

Diberikan file seperti itu

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

Apakah ada utilitas baris perintah untuk memindahkan konten sehingga output muncul seperti itu

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

Jawaban:

6
ruby -rcsv -e 'puts CSV.parse(STDIN).transpose.map &:to_csv' < in.csv > out.csv
luikore
sumber
Mengingat usia pertanyaan ini, saya akan membenarkan perubahan saya terhadap hal ini sebagai yang diterima: a) Jawaban ini jauh lebih ringkas daripada Gilles python, b) rubytidak kalah portabel daripada python, dan c) ini juga menunjukkan cara untuk melewatkan input / output file. Bravo @luikore, dan selamat datang di Unix & Linux. Silakan tinggal.
Cory Klein
satu peringatan, di csv, bidang harus dikutip
yosefrow
@yosefrow Tidak perlu mengutip. Saya menguji perintah sebelum saya memposting jawaban ini.
luikore
ok seharusnya mengatakan "mungkin" kalau begitu. Itu tidak berhasil bagi saya sampai saya mengutip semua bidang. Mungkin ada hubungannya dengan konten data saya
yosefrow
16

Penguraian CSV tidak mudah dilakukan dengan alat POSIX saja, kecuali jika Anda menggunakan varian CSV yang disederhanakan tanpa kutip (sehingga koma tidak dapat muncul di bidang). Meski begitu tugas ini tampaknya tidak mudah dilakukan dengan awk atau pemrosesan teks lainnya menjadi alat. Anda dapat menggunakan Perl dengan Text::CSV, Python dengan csv, R dengan read.csv, Ruby dengan CSV , ... (Semua ini adalah bagian dari perpustakaan standar bahasa masing-masing kecuali untuk Perl.)

Misalnya, dalam 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- berhenti menjadi jahat'
sumber
11

Dari /programming//a/2776078 :

$ apt-get install csvtool

Dan kemudian bertobat

$ csvtool transpose input.csv > ouput.csv

Atau dalam pipa

$ ... | csvtool transpose - | ...
Grzegorz Wierzowiecki
sumber
1
Cantik. Hanya ... | csvtranspose | ...akan mengalahkan itu, sintaksis.
masterxilo
3

Solusi cepat & kotor :

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
sumber
apa yang diwakili oleh / tmp / l? Selain itu, bukankah akan lebih mudah untuk melewati kolom daripada garis, sesuatu di sepanjang garisfor ((i=1; i<=$num_cols; ++i)); do paste -s -d, <(cut -f$i -d, file.txt); done
iruvar
Perhatikan bahwa ini berfungsi untuk input OP, tetapi hanya karena datanya memiliki jumlah baris dan kolom yang sama, yang biasanya tidak demikian.
tokland
csv memiliki spesifikasi mengenai kutipan dpuble, yaitu this "is" examplesel dikodekan "this ""is"" example"Saya tidak yakin jika solusi ini menangani kasus-kasus seperti itu dengan benar
Grzegorz Wierzowiecki
0

Dengan batasan yang disarankan (tanpa kutip, tidak ada koma yang disematkan), ini sederhana dalam awk (karena akan dalam perl tidak memperhitungkan lebih dari seribu baris CSV.pm, 2300 baris dalam csv.rb- python hanya memiliki 450 baris csv.py).

Ini adalah contoh untuk 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];
    }
}

By the way: contoh yang diberikan memiliki ruang ekstra yang diasumsikan OP akan dihapus; contoh lain tidak membahas detail ini.

Thomas Dickey
sumber