2011-07-14 45 views
1

結合兩個csv文件並將結果追加到perl中同一行的最佳方式是什麼?結合CSV文件

例如,一個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文件,以查看哪些用戶匹配,然後應用t他的主人到了線的盡頭。

到目前爲止,我讀這兩個文件到數組,然後我迷路

我會後的代碼,但它是一個更大的腳本

回答

4

這聽起來最適合的哈希。首先將一個文件讀入散列,然後添加另一個文件。可能會添加一個文件中存在但不存在的值的警告。

喜歡的東西:

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的方法。我對模塊不太熟悉,但它似乎在我的測試中工作。

+1

+1,但我也使用[Text :: CSV](http://search.cpan.org/~makamaka/Text-CSV-1.21/lib/Text/CSV.pm)而不是'split'。 – Dallaylaen

+0

我結束了使用這個答案的修改後的版本。由於腳本的其他部分(工作更多)已經在perl中,所以用bash編寫的其他答案將不起作用。謝謝 – zoite

+0

@zoite我已經寫了一個使用Text :: CSV的更新版本,正如評論中所建議的那樣。 – TLP

2

貌似爲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

如果文件中有不同數量的用戶,這項工作是否可行? – TLP

+0

@TLP:是的 - 如果一個文件中有16個不同的用戶,而另一個文件中有37個(其中只有12個是共同的),則非常高興。常用的將被打印;除非您調整選項以「加入」,否則其他人將被忽略。此外,如果File1中有3個用戶user23和4個File2,則會看到十幾行輸出,就像在關係數據庫中使用連接一樣。如果合適,您也可以加入多個專欄。 'join'命令強大但很挑剔。 –

+0

+1非常好的解決方案。 – TLP

0

假設1日有2個逗號,第二個只有一個,你會得到第一個文件的所有行,但只有2次的匹配的:

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