2015-06-08 2 views
0

Я начинаю с Perl и пытаюсь написать скрипт для сравнения двух хэшей и распечатать значения в первом хэше, которые не найдены во втором. Хотя я знаю, что сценарий должен быть очень простым, я не уверен, почему мой не работает. Любая помощь приветствуется.Perl сравнение двух хешей

Мой сценарий до сих пор:

#!/usr/bin/perl 
use strict; 
use warnings; 
use vars qw($a $b $c $d $hash1 %hash1 $info1 $hash2 %hash2); 

open (FILE1, "<file1.txt") || die "$!\n Couldn't open file1.txt\n"; 

while (<FILE1>){ 
    chomp (my $line=$_); 
    my ($a, $b, $c, $d) = split (/\t/, $line); 
    if ($a){ 
     $hash1 -> {$a} -> {info1} = "$b\t$c\t$d"; 
     } 
     $info1=$hash1->{$a}->{info1}; 
} 



open (FILE2, "<file2.txt") || die "$!\n Couldnt open file2.txt \n"; 
open (Output, ">Output.txt")||die "Can't Open Output file"; 



while (<FILE2>) { 
    chomp (my $line=$_); 

    my ($a, $b, $c, $d) = split (/\t/, $line); 
    if ($a){ 
    $hash2 -> {$a} -> {info2} = "$b\t$c\t$d"; 
    } 


foreach (my $hash1->{$a}) { 
    if (!exists $hash2{$a}) { 
       print Output "$a\t$info1\n"; 
         } 
     } 
} 

close FILE1; 
close FILE2; 
close Output; 

print "Done!\n"; 
+3

Имея разные переменные с тем же именем (кроме сигилы), как '% hash1' и' $ hash1' только идти чтобы вызвать у вас горе. –

+2

В этом крошечном сценарии существует огромное количество плохих практик. Я настоятельно рекомендую читать _Perl Best Practices_, чтобы избежать некоторых ошибок в использовании Perl. Нет необходимости формировать вредные привычки при изучении Perl нового в данный момент времени. – b4hand

+1

В частности, прагма 'use vars' сильно обескуражена. Кроме того, мы не можем видеть, что представляют собой ваши входные файлы. Поэтому сложно сказать, что пытается сделать ваша программа. – b4hand

ответ

1

Я обнаружил, что, кажется, несколько ошибок в программе. Я переформатировать свой код и левые комментарии к точным местоположениям ошибок ниже:

#!/usr/bin/env perl 

use strict; 
use warnings; 

use autodie; 

# use 3-arg open 
open my $file1, '<', 'file1.txt'; # no need to check errors with autodie 

# declare your lexical variables in the proper scope  
my $hash1 = {}; 
while (my $line = <$file1>) { 
    chomp $line; 
    my ($a, $b, $c, $d) = split /\t/, $line; 
    if ($a) { 
     $hash1->{$a}{info1} = "$b\t$c\t$d"; 
    } 
    # It's unclear why you are assigning to this variable? 
    my $info1 = $hash1->{$a}{info1}; 
} 

open my $file2, '<', 'file2.txt'; 
open my $output, '>', 'Output.txt'; 

# same thing here: declare your lexical variables 
my $hash2 = {}; 
while (my $line = <$file2>) { 
    chomp $line; 

    my ($a, $b, $c, $d) = split (/\t/, $line); 
    if ($a) { 
     $hash2->{$a}{info2} = "$b\t$c\t$d"; 
    } 

    # BUG: You can't iterate over a hash directly, but you 
    # can iterate over the keys of a hash. 
    foreach my $key (keys %$hash1) { 
     # BUG: You wrote `$hash2{$a}`, but probably meant `$hash2->{$a}`. 
     if (!exists $hash2->{$key}) { 
      # BUG: I think you probably meant for the following 
      # `$info1` reference to refer to the value inside 
      # `$hash1->{a}` and not the last line from the prior 
      # loop. Using lexical variables will detect these 
      # types of problems. 
      my $info1 = $hash1->{$key}{info1}; 
      print {$output} "$key\t$info1\n"; 
     } 
    } 
} 

# If you use lexical file handles, calling close is not required. They 
# get closed at the end of the containing scope, which in this case is 
# the end of the script. 

print "Done!\n"; 
2

Вы можете взять все ключи от %h1 и удалить все ключи от %h2, который оставляет только ключи, которые не находятся в %h2,

my %h1 = qw(k1 v1 k2 v2 k3 v3 k4 v4); 
my %h2 = qw(k1 v1 k2 v2 k3 v3); 

my %not_found_in_h2 = %h1; 
delete @not_found_in_h2{keys %h2}; 

print "$_\n" for values %not_found_in_h2; 

выход

v4 
Смежные вопросы