Объединить файлы CSV - PullRequest
       22

Объединить файлы CSV

1 голос
/ 15 июля 2011

Как лучше всего объединить два CSV-файла и добавить результаты в одну строку в Perl?

Например, один CSV-файл выглядит как

1234,user1,server
4323,user2,server
532,user3,server

Второй выглядит как

user1,owner
user2,owner
user3,owner1

Я хочу, чтобы результат выглядел так:

1234,user1,server,owner
4323,user2,server,owner
532,user3,server,owner1

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

Пока я прочитал в обоих файлах массивы, а потом заблудился

Я бы опубликовал код, но это часть гораздо большего скрипта

Ответы [ 3 ]

4 голосов
/ 15 июля 2011

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

Что-то вроде:

use warnings;
use strict;
use Text::CSV;
use autodie;

my %data;
my $file1 = "user.csv";
my $file2 = "user2.csv";

my $csv = Text::CSV->new ( { binary => 1 } );

open my $fh, '<', $file1;
while (my $row = $csv->getline($fh)) {
    my ($num, $user, $server) = @$row;
    $data{$user} = { 'num' => $num, 'server' => $server };
}

open $fh, '<', $file2;
while (my $row = $csv->getline($fh)) {
    my ($user, $owner) = @$row;
    if (not defined $data{$user}) {
         # warning? something else appropriate
    } else {
         $data{$user}{'owner'} = $owner;
    }
}

for my $user (keys %data) {
    print join(',', $data{$user}{'num'}, $user, $data{$user}{'server'}, 
         $data{$user}{'owner'}), "\n";
}

Редактировать: как рекомендовано в комментариях и других ответах, я изменил метод извлечения данных, используя Text :: CSV вместо split. Я не слишком знаком с модулем, но, похоже, он работает в моем тестировании.

2 голосов
/ 15 июля 2011

Выглядит как прямое приложение для команды join (связано с sort). Это предполагает, что данные так же просты, как показано - без запятых в строках или чего-то неприятного.

sort -t, -k 2 file1 > file1.sorted
sort -t, -k 1 file2 > file2.sorted
join -t, -1 2 -2 1 file1.sorted file2.sorted

С bash вы можете сделать все это в одной строке.

Если вы действительно хотите сделать это в Perl, то вам нужно использовать хеш-код, задаваемый пользовательским столбцом, потенциально с массивом записей на каждый хеш-ключ. Затем вы перебираете ключи одного из хэшей, извлекаете совпадающие значения из другого и печатаете данные. Если вы находитесь в Perl, вы можете использовать модуль Text :: CSV для точного разделения CSV.

0 голосов
/ 15 июля 2011

Предполагая, что у 1 есть 2 запятые, а у 2 только одна, вы получите все строки 1-го файла, но только совпадающие строки 2-го:

my %content;
while( <$file1> ) {
    chomp;
    /,(.+),/;
    $content{$1} = "$_,";
}
while( <$file2> ) {
    chomp;
    /(.+),(.+)/;
    $content{$1} .= $2;
}
print "$content{$_}\n" for sort keys %content;
...