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

Odpowiedzi:


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

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


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

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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.