Есть ли утилита командной строки для транспонирования csv-файла?

16

Учитывая файл, как так

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

Есть ли утилита командной строки для транспонирования содержимого, чтобы вывод выглядел так

First,Cory,John Jacob
Last,Klein,Smith
Age,27,30
Кори Кляйн
источник

Ответы:

6
ruby -rcsv -e 'puts CSV.parse(STDIN).transpose.map &:to_csv' < in.csv > out.csv
luikore
источник
Учитывая возраст этого вопроса, я оправдываю свое изменение на это как принятое: а) этот ответ гораздо более лаконичен, чем Жиль python, б) rubyне менее переносим, ​​чем python, и в) это также показывает, как передать ввод / вывод файлы. Браво @luikore, и добро пожаловать в Unix & Linux. Пожалуйста, не торопись.
Кори Кляйн
одна оговорка, в csv, поля должны быть
заключены в
@yosefrow Не нужно цитировать. Я проверил команду, прежде чем опубликовать этот ответ.
Луйкоре
хорошо, должен был сказать "может" тогда. Это не сработало для меня, пока я не процитировал все поля. Может быть, связано с моим содержанием данных
yosefrow
16

Синтаксический анализ CSV нелегко выполнить только с помощью инструментов POSIX, если только вы не используете упрощенный вариант CSV без кавычек (чтобы запятые не могли появляться в поле). Даже тогда эта задача не кажется простой для выполнения с помощью awk или другой обработки текста в инструменте. Вы можете использовать Perl с Text::CSV, Python с csv, R с read.csv, Ruby с CSV ,… (Все это является частью стандартной библиотеки соответствующего языка, за исключением Perl.)

Например, в 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])
Жиль "ТАК - прекрати быть злым"
источник
11

С /programming//a/2776078 :

$ apt-get install csvtool

А потом конвертировать

$ csvtool transpose input.csv > ouput.csv

Или в конвейере

$ ... | csvtool transpose - | ...
Гжегож Вежовецкий
источник
1
прекрасный. Только ... | csvtranspose | ...побил бы это, с точки зрения синтаксиса.
masterxilo
3

Быстрое и грязное решение для :

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++))
}
Жиль Квено
источник
что представляет собой / tmp / l? Кроме того, не будет ли проще циклически проходить по столбцам, а не по линиям, что-то вродеfor ((i=1; i<=$num_cols; ++i)); do paste -s -d, <(cut -f$i -d, file.txt); done
iruvar
Обратите внимание, что это работает для ввода OP, но только потому, что их данные имеют одинаковое количество строк и столбцов, что, как правило, не так.
Tokland
CSV имеет спецификацию относительно кавычек dpuble, т. е. this "is" exampleячейка закодирована. "this ""is"" example"Я не уверен, что это решение правильно обрабатывает такие случаи
Grzegorz Wierzowiecki
0

Учитывая предлагаемое ограничение (без кавычек, без встроенных запятых), это просто в awk (как это было бы в perl, не принимая во внимание более тысячи строк в CSV.pm, 2300 строк вcsv.rb - в python только 450 строк csv.py).

Вот пример для 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];
    }
}

Кстати: в данном примере было дополнительное пространство, которое, как предполагал OP, будет удалено; другие примеры не касались этой детали.

Томас Дики
источник