Czy istnieje narzędzie wiersza polecenia do transponowania pliku csv?

16

Biorąc pod uwagę taki plik

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

Czy istnieje narzędzie wiersza polecenia do transponowania zawartości, aby dane wyjściowe wyglądały tak

First,Cory,John Jacob
Last,Klein,Smith
Age,27,30
Cory Klein
źródło

Odpowiedzi:

6
ruby -rcsv -e 'puts CSV.parse(STDIN).transpose.map &:to_csv' < in.csv > out.csv
luikore
źródło
Biorąc pod uwagę wiek tego pytania, uzasadnię moją zmianę na to, co zostało zaakceptowane: a) Ta odpowiedź jest o wiele bardziej zwięzła niż Gillesa python, b) rubyjest nie mniej przenośna niż python, i c) pokazuje także, jak przekazać wejście / wyjście akta. Bravo @luikore, witamy w systemach Unix i Linux. Proszę, trzymaj się.
Cory Klein
jedno zastrzeżenie, w csv, pola muszą być cytowane
yosefrow
@yosefrow Nie trzeba cytować. Przetestowałem polecenie przed opublikowaniem tej odpowiedzi.
luikore,
ok powinienem wtedy powiedzieć „może”. Nie zadziałało, dopóki nie zacytowałem wszystkich pól. Może to mieć związek z moją zawartością danych
yosefrow
16

Analiza składni CSV nie jest łatwa do wykonania tylko za pomocą narzędzi POSIX, chyba że używasz uproszczonego wariantu CSV bez cudzysłowu (aby przecinki nie pojawiały się w polu). Nawet wtedy to zadanie nie wydaje się łatwe do wykonania z awk lub innym przetwarzaniem tekstu w narzędziu. Możesz używać Perla z Text::CSV, Pythona z csv, R z read.csv, Ruby z CSV ,… (Wszystkie są częścią standardowej biblioteki odpowiedniego języka z wyjątkiem Perla.)

Na przykład w Pythonie:

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- przestań być zły”
źródło
11

Od /programming//a/2776078 :

$ apt-get install csvtool

A następnie przekonwertować

$ csvtool transpose input.csv > ouput.csv

Lub w przygotowaniu

$ ... | csvtool transpose - | ...
Grzegorz Wierzowiecki
źródło
1
piękny. Pokonałby ... | csvtranspose | ...to tylko pod względem składniowym.
masterxilo
3

Szybkie i brudne rozwiązanie :

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
źródło
co oznacza / tmp / l? Ponadto, czy nie byłoby łatwiej zapętlić kolumny, a nie linie, coś wzdłuż liniifor ((i=1; i<=$num_cols; ++i)); do paste -s -d, <(cut -f$i -d, file.txt); done
iruvar
Zauważ, że działa to dla danych wejściowych OP, ale tylko dlatego, że ich dane mają taką samą liczbę wierszy i kolumn, co zwykle nie jest prawdą.
tokland
csv ma ​​specyfikację dotyczącą cytatów dpuble, tj. this "is" examplekomórka jest zakodowana "this ""is"" example"Nie jestem przekonany, czy to rozwiązanie odpowiednio obsługuje takie przypadki
Grzegorz Wierzowiecki,
0

Biorąc pod uwagę sugerowane ograniczenie (bez cudzysłowu, bez osadzonych przecinków), jest on prosty w awk (tak jak w perlu, nie biorąc pod uwagę ponad tysiąca linii w CSV.pm, 2300 linii w csv.rb- python ma tylko 450 linii w csv.py).

Oto przykład 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];
    }
}

Nawiasem mówiąc: podany przykład miał dodatkową przestrzeń, która, jak zakładano, zostanie usunięta; inne przykłady nie dotyczyły tego szczegółu.

Thomas Dickey
źródło