Intereting Posts
Компьютерный терминал и виртуальная консоль Печать на «стандартном выходе» и «стандартной ошибке» Лучший менеджер окон для одного приложения Извлечение данных в linux / unix Как предоставить разрешения другому пользователю после регистрации в качестве пользователя root в Linux? Непоследовательность в поведении «rm» при подключенном томе? Многоадресный UDP не работает файловая система unionfs Как защитить малиновый пирог, контролируемый SSH, против вредоносной программы Linux.MulDrop.14? Усечение точности даты Dovecot с сертификатами CAcert, Outlook не может подключиться к IMAP Bash ждет рабочих мест и ограничивает количество заданий Как найти файл – это жесткая ссылка или символическая ссылка? Как добавить строку в файл, который имеет только права на запись в root и продолжить выполнение скрипта Связь между исполняемым скриптом zsh и конфигурацией compsys / zstyle

Объединение содержимого нескольких CSV-файлов в один файл .csv

Я хочу написать скрипт, который объединяет содержимое нескольких CSV-файлов в один CSV-файл, т.е. добавляет столбцы всех других файлов в столбцы первого файла. Я попытался сделать это, используя цикл «для», но не смог продолжить его.

Кто-нибудь знает, как это сделать в Linux?

Вот скрипт perl, который читает в каждой строке каждого файла, указанного в командной строке, и добавляет его к элементам в массиве ( @csv ). Когда ввода больше нет, он выводит каждый элемент @csv .

Файлы .csv будут добавляться в том порядке, в котором они указаны в командной строке.

ПРЕДУПРЕЖДЕНИЕ . Этот сценарий предполагает, что все входные файлы имеют одинаковое количество строк . Вывод, вероятно, будет непригодным, если какой-либо файл имеет другое количество строк от любого другого.

 #!/usr/bin/perl use strict; my @csv=(); foreach (@ARGV) { my $linenum=0; open(F,"<",$_) or die "couldn't open $_ for read: $!\n"; while (<F>) { chomp; $csv[$linenum++] .= "," . $_; }; close(F); }; foreach (@csv) { s/^,//; # strip leading comma from line print $_,"\n"; }; 

Учитывая следующие входные файлы:

 ==> 1.csv <== 1,2,3,4 1,2,3,4 1,2,3,4 1,2,3,4 ==> 2.csv <== 5,6,7,8 5,6,7,8 5,6,7,8 5,6,7,8 ==> 3.csv <== 9,10,11,12 9,10,11,12 9,10,11,12 9,10,11,12 

он будет производить следующий вывод:

 $ ./mergecsv.pl *.csv 1,2,3,4,5,6,7,8,9,10,11,12 1,2,3,4,5,6,7,8,9,10,11,12 1,2,3,4,5,6,7,8,9,10,11,12 1,2,3,4,5,6,7,8,9,10,11,12 

Хорошо, теперь, когда вы прочли это, пришло время признать, что это не делает ничего, что не paste -d, *.csv . Так зачем беспокоиться о perl? paste довольно негибкая. Если ваши данные в точности соответствуют тому, что делает paste , вы хороши – это идеально подходит для работы и очень быстро. Если нет, это совершенно бесполезно для вас.

Существует несколько способов улучшения такого Perl-скрипта (например, обработка файлов разной длины путем подсчета количества полей для каждого файла и добавления правильного количества пустых полей в @csv для каждого файла (ов), который отсутствуют строки или, по крайней мере, обнаруживают разные длины и выходят с ошибкой), но это разумная отправная точка, если требуется более сложное слияние.

BTW, это использует действительно простой алгоритм и сохраняет все содержимое всех входных файлов в памяти (в @csv ) сразу. Для файлов до нескольких МБ каждый в современной системе это не является необоснованным. Если, однако, вы обрабатываете HUGE .csv-файлы, лучшим алгоритмом будет:

  • откройте все входные файлы и, хотя есть еще данные для чтения:
    • читать строку из каждого файла
    • добавьте строки (в порядке @ARGV)
    • распечатать прилагаемую строку

Самый простой способ достижения этой цели – ввести следующую команду

 cat *csv > combined.csv 

Этот файл будет содержать содержимое всех ваших файлов csv именно так, как вы упомянули.