2012-02-09 51 views
3

我有三個文件,每個文件都有一個ID和一個值。Unix加入兩個以上的文件

[email protected]:~/test$ ls 
a.txt b.txt c.txt 
[email protected]:~/test$ cat a.txt 
id1 1 
id2 2 
id3 3 
[email protected]:~/test$ cat b.txt 
id1 4 
id2 5 
id3 6 
[email protected]:~/test$ cat c.txt 
id1 7 
id2 8 
id3 9 

我想創建一個類似如下的文件...

id1 1 4 7 
id2 2 5 8 
id3 3 6 9 

...最好使用一個命令。

我知道加入和粘貼命令。粘貼每次都會重複的ID列:

[email protected]:~/test$ paste a.txt b.txt c.txt 
id1 1 id1 4 id1 7 
id2 2 id2 5 id2 8 
id3 3 id3 6 id3 9 

加入效果很好,但在同一時間只有兩個文件:

[email protected]:~/test$ join a.txt b.txt 
id1 1 4 
id2 2 5 
id3 3 6 
[email protected]:~/test$ join a.txt b.txt c.txt 
join: extra operand `c.txt' 
Try `join --help' for more information. 

我也知道這種糊可以採取STDIN爲一體通過使用「 - 」參數。例如,我可以使用以下命令來複制連接命令:

[email protected]:~/test$ cut -f2 b.txt | paste a.txt - 
id1 1 4 
id2 2 5 
id3 3 6 

但我仍然不確定如何修改此以容納三個文件。

因爲我在perl腳本中這樣做,我知道我可以做一些事情,比如把它放在一個foreach循環中,就像加入file1 file2> tmp1,加入tmp1 file3> tmp2等。但是這會變得凌亂,我想用一行代碼來做到這一點。

+0

我也知道這是一個SQL內部連接的小菜一碟,但我不想先將所有這些加載到數據庫中。 – 2012-02-09 14:46:43

回答

12

join a.txt b.txt|join - c.txt

既然你這樣做Perl腳本內應足以

+1

或者:'加入<(加入a.txt b.txt)c.txt' – jts 2012-02-09 15:31:14

+0

這很好。加入一個b |加入 - c |加入 - 等等。該腳本比<(加入)版本更容易編寫腳本,但也可行。謝謝! – 2012-02-09 18:52:01

1

,有沒有你不這樣做在Perl的工作,而不是在外殼產卵任何具體的原因是什麼?

喜歡的東西(未測試買者自負!):

use File::Slurp; # Slurp the files in if they aren't too big 
my @files = qw(a.txt b.txt c.txt); 
my %file_data = map ($_ => [ read_file($_) ]) @files; 
my @id_orders; 
my %data =(); 
my $first_file = 1; 
foreach my $file (@files) { 
    foreach my $line (@{ $file_data{$file} }) { 
     my ($id, $value) = split(/\s+/, $line); 
     push @id_orders, $id if $first_file; 
     $data{$id} ||= []; 
     push @{ $data{$id} }, $value; 
    } 
    $first_file = 0; 
} 
foreach my $id (@id_orders) { 
    print "$d " . join(" ", @{ $data{$id} }) . "\n"; 
} 
+0

這是我希望能夠在命令行上做的事情。我基本上使用perl來粘合其他人(python,C++等)編寫的一些其他程序和腳本。 a.txt,b.txt等是從一個python腳本輸出的,我現在需要將它們混合在一起,然後將它們導入到統計程序中。 – 2012-02-09 15:03:48

+0

@StephenTurner - 只要你不介意支付產卵殼程序的(不是太大)懲罰/成本,當然。 – DVK 2012-02-09 15:53:08

0

perl -lanE'$h{$F[0]} .= " $F[1]" END{say $_.$h{$_} foreach keys %h}' *.txt

應該工作,無法測試它,因爲我從我的手機接聽。如果您在foreachkeys之間輸入sort,也可以對輸出進行排序。

0
pr -m -t -s\ file1.txt file2.txt|gawk '{print $1"\t"$2"\t"$3"\t"$4}'> finalfile.txt 

考慮文件1和file2有2列1和2表示從file1和3和4代表從文件2列的列。

您也可以用這種方式打印每個文件中的任何列,並且它會將任意數量的文件作爲輸入。例如,如果你的file1有5列,那麼$ 6將是file2的第一列。