我很长时间不使用perl编程,需要一些推动。
我需要比较两个列表,以便仅保留不匹配的行。
我的第一个文件如下:
1 pf1 er2 0,4
2 pf1 er3 0,56
3 pf1 er6 0,72365
4 er3 pf3 0,263
5 pf5 er2 0,28473
第二个文件是:
pf1 er2
pf1 er3
er2 pf1
er3 pf1
我想要一个输出,如:
3 pf1 er6 0,72365
4 er3 pf3 0,263
5 pf5 er2 0,28473
我以前是通过grep -Fvf second_file.txt first-file.txt > output.txt
现在我需要在perl中执行相同的操作,但是我无法组织代码。
open(HAN, "< $file_1") || die "Impossibile aprire il file $file_1";
@r = <HAN>;
close(HAN);
open(RES, "< $file_2") || die "Impossibile aprire il file $file_2";
@c = <RES>;
close(RES);
for ($i=0; $i<=$#r; $i++){
($num, $id1, $id2, $v) = split (/\t/, $r[$i], 4);
$ppi1 = $id1."\t".$id2;
for($t=0; $t<=$#c; $t++){
($iid1, $iid2) = split (/ /, $c[$t]);
$orto1 = $iid1."\t".$iid2;
$orto2 = $iid2."\t".$iid1;
if( ($ppi1 ne $orto1) || ($ppi1 ne $orto2) ){
print "$ppi1\n";
}
}
}
任何建议都非常欢迎!
答案 0 :(得分:2)
基于该样本数据,如果第二列和第三列与第二个文件的一行的第一列和第二列匹配,则要从第一文件中排除行。将第二个文件的列存储在哈希中,然后在读取第一个文件时检查这些键的存在是一种简单,非常省时的方法:
#!/usr/bin/perl
use warnings;
use strict;
use autodie;
my ($data_file, $excludes_file) = @ARGV;
my %excludes;
open my $ex, "<", $excludes_file;
while (<$ex>) {
chomp;
my @F = split;
$excludes{$F[0]}->{$F[1]} = 1;
}
open my $data, "<", $data_file;
while (<$data>) {
my @F = split;
print unless exists $excludes{$F[1]}->{$F[2]};
}
运行它将给出:
$ perl filter.pl file1.txt file2.txt
3 pf1 er6 0,72365
4 er3 pf3 0,263
5 pf5 er2 0,28473
答案 1 :(得分:1)
这不是一个非常详尽但可行的解决方案:
#!/usr/bin/env perl
use strict;
use warnings;
use 5.010;
use Data::Dumper;
#my @first_file_lines = split "\n", `cat ./first_file.txt`;
#my @second_file_lines = split "\n",`cat ./second_file.txt`;
open( my $fh, '<', './first_file.txt' );
open( my $fh1, '<', './second_file.txt' );
chomp ( my @first_file_lines = <$fh> );
chomp (my @second_file_lines = <$fh1>) ;
close( $fh );
close( $fh1 );
my @output = grep { filter( $_, \@second_file_lines ) } @first_file_lines;
sub filter {
my $current = shift;
my $compare_to = shift;
for my $comp ( @$compare_to ) {
my $comp1 = $comp;
$comp1 =~ s/\|/ /;
if ( $current =~ /^$comp1/ ) {
say 'equal: ' . "$current : $comp";
return;
}
}
return $current;
}
say Dumper( @first_file_lines );
say Dumper( @second_file_lines );
for my $out ( @output ) {
`echo "$out" >> ./output.txt`;
}
答案 2 :(得分:1)
这应该有效:
(?:pf1 er2|pf1 er3|er2 pf1|er3 pf1)
#!/usr/bin/perl
use strict;
use warnings;
my($reference) = @ARGV;
my $fh;
open($fh, "<". $reference)
or die "open '${reference}': $!\n";
my @matches;
while (<$fh>) {
chomp;
push(@matches, quotemeta);
}
close($fh)
or die "close '${reference}': $!\n";
# compile combined regex
my $regex = join('|', @matches);
$regex = qr/(?:${regex})/;
while (<STDIN>) {
print unless $_ =~ $regex;
}
exit 0;
测试输出:
$ cat dummy1.txt
1 pf1 er2 0,4
2 pf1 er3 0,56
3 pf1 er6 0,72365
4 er3 pf3 0,263
5 pf5 er2 0,28473
$ cat dummy2.txt
pf1 er2
pf1 er3
er2 pf1
er3 pf1
$ perl dummy.pl <dummy1.txt dummy2.txt
3 pf1 er6 0,72365
4 er3 pf3 0,263
5 pf5 er2 0,28473