我遇到了一个简单的问题。我需要比较两个文件,只写出两者之间不匹配的模式。
我的第一个文件如下:
1 A A
2 A B
3 C D
4 E F
5 G H
6 I L
我的第二个文件如下:
A A
A B
C D
我想要的是使用第二个文件中的对列表来选择第一个文件中的不匹配行并在输出中打印它们。我想要的输出如下:
4 E F
5 G H
6 I L
我的代码需要改进,我需要你的帮助来做到这一点!
open (FUS, "< $file_1")|| die "Impossible open file 1";
@f = <FUS>;
close (FUS);
open (ALL, "< $file_2")|| die "Impossible open file 2";
@a = <ALL>;
close (ALL);
for ($c=0; $c<=$#a; $c++) {
chomp ($a[$c]);
@q = split (/\t/, $a[$c]);
$qok = $q[0]."\t".$q[1];
$qko = $q[1]."\t".$q[0];
for ($t=0; $t<=$#f; $t++) {
chomp ($f[$t]);
($id, $pf1, $pf2) = split (/\t/, $f[$t]);
$pf_12 = $pf1."\t".$pf2;
$pf_21 = $pf2."\t".$pf1;
if ((($qok ne $pf_12) && ($qko ne $pf_12)) || (($qok ne $pf_21) && ($ko ne $pf_21))){
print "$id\t$pf1\t$pf2\n";
}
}
}
这段代码的问题在循环中会导致我得到错误的结果而不是所需的结果。
非常欢迎任何建议!
答案 0 :(得分:5)
如果您愿意,可以使用grep
轻松实现:
$ grep -Fvf b.txt a.txt
4 E F
5 G H
6 I L
-F
表示“固定字符串”,-v
表示“反转匹配”,-f
表示“从文件读取模式,每行一个”。
答案 1 :(得分:1)
实现此目的的通常方法是将第二个文件存储在哈希中:
open my $ALL, '<', $file_2 or die "$file_2 : $!";
my %hash;
while (<$ALL>) {
chomp;
$hash{$_} = 1;
}
open my $FUS, '<', $file_1 or die "$file_1 : $!";
while (<$FUS>) {
my ($columns) = / (.*)/;
print unless exists $hash{$columns};
}
答案 2 :(得分:1)
如果您的文件不是太大,我建议使用哈希:
1)使用as键填充%hash_a字符串所需的匹配部分。读取文件后,此哈希将包含以下内容:
%hash_a = (
'A A' => '1 A A',
'A B' => '2 A B',
...
'I L' => '6 I L'
);
2)迭代第二个文件,并从%hash_a中删除正确的密钥:
$key =<$file>;
chomp $key;
delete $hash_a{$key};
3)打印%hash_a
上的剩余键另外,我建议你:
use strict; use warnings;
open my $FUS, '<', $file_1 or die "Cannot open $file_1: $!";