我已经问了这个问题(很抱歉再次提问,这次是不同而且困难)但是我已经尝试了很多但没有达到结果。
我有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;
}
}
}
}
是不是?
答案 0 :(得分:1)
您不需要两个哈希表。您只需要从第一个文件中的条目构建一个哈希表,当您遍历第二个文件时,使用defined
检查第一个文件哈希表中是否存在密钥。
如果有密钥,请对其他列的值进行比较(我们将哈希表中第一个文件的值存储为第三列的密钥)。
如果没有密钥,那么warn
,die
或者让脚本继续运行而不说任何话,如果这就是你想要的:
#!/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