Perl比较两个哈希

时间:2015-06-08 02:24:13

标签: perl hash compare

我是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";

2 个答案:

答案 0 :(得分: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

答案 1 :(得分: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";