使用perl哈希来比较2个文件的列

时间:2012-01-31 10:29:01

标签: perl

我已经问了这个问题(很抱歉再次提问,这次是不同而且困难)但是我已经尝试了很多但没有达到结果。

我有2个大文件(制表符分隔)。

第一个文件 - >

Col1           Col2    Col3 Col4     Col5        Col6       Col7    Col8
101_#2          1       H    F0       263        278        2       1.5
102_#1          1       6    F1       766        781        1       1.0
103_#1          2       15   V1       526        581        1       0.0
103_#1          2       9    V2       124        134        1       1.3
104_#1          1       12   V3       137        172        1       1.0
105_#1          1       17   F2       766        771        1       1.0

第二个文件 - >

Col1    Col2    Col3             Col4
97486   H   262               279
67486   9   118           119
87486   9   183           185
248233  9   124           134

如果col3值/字符(file1)和col2值/字符(文件2)相同,然后将文件1的col5和col6(如范围值)与file2的col3和col4进行比较,如果文件范围1出现在文件2中,然后返回该行(来自file1),并在输出中添加来自file2的额外column1。

预期输出 - >

Col1      Col2    Col3 Col4     Col5        Col6       Col7    Col8   Col9
101_#2        1       H    F0       263        278        2       1.5       97486
103_#1        2       9    V2       124        134        1       1.3       248233 

到目前为止,我已尝试使用哈希 - >

@ARGV or die "No input file specified";
open my $first, '<',$ARGV[0] or die "Unable to open input file: $!";
open my $second,'<', $ARGV[1] or die "Unable to open input file: $!";
print scalar (<$first>);
while(<$second>){
    chomp;
    @line=split /\s+/;
    $hash{$line[2]}=$line[3];
}
while (<$first>) {
    @cols = split /\s+/;
    $p1 = $cols[4];
    $p2 = $cols[5];
    foreach $key (sort keys %hash){
        if ($p1>= "$key"){
            if ($p2<=$hash{$key})
            {
                print join("\t",@cols),"\n";
            }
        }
        else{ next; }
    }
}

但是在上面的代码中没有比较col3值/字符(file1)和col2值/字符(文件2)。 但是这也花费了大量的时间和记忆。任何人都可以建议我如何使用哈希哈希或哈希来快速制作它。非常感谢。

大家好,

非常感谢你的帮助。我想出了一个有效的方法来解决我自己的问题。

@ARGV or die "No input file specified";
open $first, '<',$ARGV[0] or die "Unable to open input file: $!";
open $second,'<', $ARGV[1] or die "Unable to open input file: $!";
print scalar (<$first>);


while(<$second>){
chomp;
@line=split /\s+/;

    $hash{$line[1]}{$line[2]}{$line[3]}= $line[0];
    }
while (<$first>) {

    @cols = split /\s+/;

foreach  $key1 (sort keys %hash) {
   foreach $key2 (sort keys %{$hash{$key1}}) {
        foreach  $key3 (sort keys %{$hash{$key1}{$key2}}) {
        if (($cols[2] eq $key1) && ($cols[4]>=$key2) && ($cols[5]<=$key3)){
            print join("\t",@cols),"\t",$hash{$key1}{$key2}{$key3},"\n";

        }   
        last;
    }

}
}
}

是不是?

2 个答案:

答案 0 :(得分:1)

您不需要两个哈希表。您只需要从第一个文件中的条目构建一个哈希表,当您遍历第二个文件时,使用defined检查第一个文件哈希表中是否存在密钥。

如果有密钥,请对其他列的值进行比较(我们将哈希表中第一个文件的值存储为第三列的密钥)。

如果没有密钥,那么warndie或者让脚本继续运行而不说任何话,如果这就是你想要的:

#!/usr/bin/perl -w

use strict;
use warnings;

my $firstHashRef;

open FIRST, "< $firstFile" or die "could not open first file...\n";
while (<FIRST>) { 
    chomp $_;
    my @elements = split "\t", $_;
    my $col3Val = $elements[2];  # Perl arrays are zero-indexed
    my $col5Val = $elements[4];
    my $col6Val = $elements[5];

    # keep the fifth and sixth column values on hand, for
    # when we loop through the second file...

    if (! defined $firstHashRef->{$col3Val}) { 
        $firstHashRef->{$col3Val}->{Col5} = $col5Val; 
        $firstHashRef->{$col3Val}->{Col6} = $col6Val; 
    }
}
close FIRST;

open SECOND, "< $secondFile" or die "could not open second file...\n";
while (<SECOND>) {
    chomp $_;
    my @elements = split "\t", $_;
    my $col2ValFromSecondFile = $elements[1];
    my $col3ValFromSecondFile = $elements[2];
    my $col4ValFromSecondFile = $elements[3];

    if (defined $firstHashRef->{$col2ValFromSecondFile}) {
        # we found a matching key
        # 1. Compare $firstHashRef->{$col2ValFromSecondFile}->{Col5} with $col3ValFromSecondFile
        # 2. Compare $firstHashRef->{$col2ValFromSecondFile}->{Col6} with $col4ValFromSecondFile
        # 3. Do something interesting, based on comparison results... (this is left to you to fill in)
    }
    else {
        warn "We did not locate entry in hash table for second file's Col2 value...\n";
    }
}
close SECOND;

答案 1 :(得分:1)

如何仅使用awk -

awk '
NR==FNR && NR>1{a[$3]=$0;b[$3]=$5;c[$3]=$6;next} 
($2 in a) && ($3<=b[$2] && $4>=c[$2]) {print a[$2],$1}' file1 file2

输入数据:

[jaypal:~/Temp] cat file1
Col1           Col2    Col3 Col4     Col5        Col6       Col7    Col8
101_#2          1       H    F0       263        278        2       1.5
109_#2          1       H    F0       263        278        2       1.5
102_#1          1       6    F1       766        781        1       1.0
103_#1          2       15   V1       526        581        1       0.0
103_#1          2       9    V2       124        134        1       1.3
104_#1          1       12   V3       137        172        1       1.0
105_#1          1       17   F2       766        771        1       1.0

[jaypal:~/Temp] cat file2
Col1    Col2    Col3    Col4
97486   H       262     279
67486   9       118     119
87486   9       183     185
248233  9       124     134

测试:

[jaypal:~/Temp] awk '
NR==FNR && NR>1{a[$3]=$0;b[$3]=$5;c[$3]=$6;next} 
($2 in a) && ($3<=b[$2] && $4>=c[$2]) {print a[$2],$1}' file1 file2
101_#2          1       H    F0       263        278        2       1.5 97486
103_#1          2       9    V2       124        134        1       1.3 248233