2012-05-03 6 views
0

J'ai deux fichiers séparés par des tabulations que je dois aligner. par exemple:fusionner deux fichiers avec des colonnes similaires

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

(Ce sont de gros fichiers, potentiellement des milliers de lignes!)

Ce que je voudrais faire est d'avoir le look de sortie comme ceci:

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

De préférence I aimerait faire cela en perl, mais je ne sais pas comment. toute aide serait grandement appréciée.

+0

Jetez un oeil à l'adresse http : //stackoverflow.com/questions/4960275/how-can-match-records-in-two-files-using-perl –

+0

avez-vous vraiment besoin de répéter l'étiquette de la ligne à chaque fois? construire un hachage de arrayrefs serait assez facile. –

Répondre

0

En supposant que les fichiers sont triés,

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

Comme mentionné Ikegami, il suppose que le contenu des fichiers sont disposés comme indiqué dans votre exemple.

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; 

En examinant votre exemple, vous montrez des paires clé/valeur identiques dans les deux fichiers. Étant donné cela, il semble que vous vouliez montrer la paire (s) unique au fichier 1, unique au fichier 2, et montrer les paires communes. Si tel est le cas (et vous n'êtes pas essayer de faire correspondre les paires de fichiers soit par des clés ou des valeurs), vous pouvez 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

Si son juste de faire une structure de données, cela peut être assez facile.

#!/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; 

Vous pouvez ensuite imprimer dans n'importe quel format. S'il s'agit vraiment d'utiliser les fichiers exactement comme ils sont, alors c'est un peu plus compliqué.

0

similaires à la réponse de Joel Berger, mais cette approche permet de vous garder une trace si des fichiers ont fait ou ne contenaient pas une clé donnée:

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); 

Sortie:

$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' 
    } 
}; 
Questions connexes