2012-05-03 8 views
0

У меня есть два разделенных вкладкой файла, которые мне нужно выровнять вместе. например:слияние двух файлов с похожими столбцами

File 1:  File 2: 
AAA 123  BBB 345 
BBB 345  CCC 333 
CCC 333  DDD 444 

(Это большие файлы, потенциально тысячи строк!)

Что я хотел бы сделать, это иметь выходной выглядеть следующим образом:

AAA 123 
BBB 345 BBB 345 
CCC 333 CCC 333 
     DDD 444 

Предпочтительно I хотел бы сделать это в perl, но не уверен, как это сделать. любая помощь была бы очень восприимчивой.

+0

Посмотрите на HTTP : //stackoverflow.com/questions/4960275/how-can-match-records-in-two-files-using-perl –

+0

Вам действительно нужно повторять ярлык строки каждый раз? создание хэша arrayrefs было бы довольно простым. –

ответ

0

Предполагая, что файлы сортируются,

sub get { 
    my ($fh) = @_; 
    my $line = <$fh>; 
    return() if !defined($line); 
    return split(' ', $line); 
} 

my ($key1, $val1) = get($fh1); 
my ($key2, $val2) = get($fh2); 

while (defined($key1) && defined($key2)) { 
    if ($key1 lt $key2) { 
     print(join("\t", $key1, $val1), "\n"); 
     ($key1, $val1) = get($fh1); 
    } 
    elsif ($key1 gt $key2) { 
     print(join("\t", '', '', $key2, $val2), "\n"); 
     ($key2, $val2) = get($fh2); 
    } 
    else { 
     print(join("\t", $key1, $val1, $key2, $val2), "\n"); 
     ($key1, $val1) = get($fh1); 
     ($key2, $val2) = get($fh2); 
    } 
} 

while (defined($key1)) { 
    print(join("\t", $key1, $val1), "\n"); 
    ($key1, $val1) = get($fh1); 
} 

while (defined($key2)) { 
    print(join("\t", '', '', $key1, $val1), "\n"); 
    ($key2, $val2) = get($fh2); 
} 
0

Как уже упоминалось Ikegami, она предполагает, что содержимое файлов которых расположены так, как показано в вашем примере.

use strict; 
use warnings; 

open my $file1, '<file1.txt' or die $!; 
open my $file2, '<file2.txt' or die $!; 

my $file1_line = <$file1>; 
print $file1_line; 

while (my $file2_line = <$file2>) { 
    if(defined($file1_line = <$file1>)) { 
     chomp $file1_line; 
     print $file1_line; 
    } 

    my $tabs = $file1_line ? "\t" : "\t\t"; 
    print "$tabs$file2_line"; 
} 

close $file1; 
close $file2; 

Рассматривая пример, вы показываете некоторые идентичные пары ключ/значение в обоих файлах. Учитывая это, похоже, что вы хотите показать пару (ы), уникальную для файла 1, уникальную для файла 2, и показать общие пары. Если это так (и вы не пытаетесь соответствовать парам файлов с помощью либо ключей или значений), вы можете use List::Compare:

use strict; 
use warnings; 
use List::Compare; 

open my $file1, '<file1.txt' or die $!; 
my @file1 = <$file1>; 
close $file1; 

open my $file2, '<file2.txt' or die $!; 
my @file2 = <$file2>; 
close $file2; 

my $lc = List::Compare->new(\@file1, \@file2); 

my @file1Only = $lc->get_Lonly; # L(eft array)only 
for(@file1Only) { print } 

my @bothFiles = $lc->get_intersection; 
for(@bothFiles) { chomp; print "$_\t$_\n" } 

my @file2Only = $lc->get_Ronly; # R(ight array)only 
for(@file2Only) { print "\t\t$_" } 
1

Если его просто о создании структуры данных, это может быть довольно легко.

#!/usr/bin/env perl 

# usage: script.pl file1 file2 ... 

use strict; 
use warnings; 

my %data; 
while (<>) { 
    chomp; 
    my ($key, $value) = split; 
    push @{$data{$key}}, $value; 
} 

use Data::Dumper; 
print Dumper \%data; 

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

0

Подобный ответ Джоэля Бергера, но этот подход позволяет вам отслеживать, делали ли файлы или не содержат данный ключ:

my %data; 

while (my $line = <>){ 
    chomp $line; 
    my ($k)   = $line =~ /^(\S+)/; 
    $data{$k}{line} = $line; 
    $data{$k}{$ARGV} = 1; 
} 

use Data::Dumper; 
print Dumper(\%data); 

Выход:

$VAR1 = { 
    'CCC' => { 
    'other.dat' => 1, 
    'data.dat' => 1, 
    'line' => 'CCC 333' 
    }, 
    'BBB' => { 
    'other.dat' => 1, 
    'data.dat' => 1, 
    'line' => 'BBB 345' 
    }, 
    'DDD' => { 
    'other.dat' => 1, 
    'line' => 'DDD 444' 
    }, 
    'AAA' => { 
    'data.dat' => 1, 
    'line' => 'AAA 123' 
    } 
}; 
Смежные вопросы