我有两个文件,每个文件有两列:
FILE1
A B
1 #
2 @
3 !
4 %
5 %
FILE 2
A B
3 #
4 !
2 &
1 %
5 ^
Perl脚本必须比较两个文件中的A列,并且只有它们相等时才必须打印FIlE 2的B列
到目前为止,我有以下代码,但我得到的是带有#B列的无限循环
use strict;
use warnings;
use 5.010;
print "enter site:"."\n";
chomp(my $s = <>);
print "enter protein:"."\n";
chomp(my $p = <>);
open( FILE, "< $s" ) or die;
open( OUT, "> PSP.txt" ) or die;
open( FILE2, "< $p" ) or die;
my @firstcol;
my @secondcol;
my @thirdcol;
while ( <FILE> )
{
next if $. <2;
chomp;
my @cols = split;
push @firstcol, $cols[0];
push @secondcol, $cols[1]."\t"."\t".$cols[3]."\t"."\t"."\t"."N\/A"."\n";
}
my @firstcol2;
my @secondcol2;
my @thirdcol2;
while ( <FILE2> )
{
next if $. <2;
my @cols2 = split(/\t/, $_);
push @firstcol2, $cols2[0];
push @secondcol2, $cols2[4]."\n";
}
my $size = @firstcol;
my $size2 = @firstcol2;
for (my $i = 0; $i <= @firstcol ; $i++) {
for (my $j = 0; $j <= @firstcol2; $j++) {
if ( $firstcol[$i] eq $firstcol2[$j] )
{
print $secondcol2[$i];
}
}
}
答案 0 :(得分:1)
my (@first, @second);
while(<first>){
chomp;
my $foo = split / /, $_;
push @first , $foo;
}
while(<second>){
chomp;
my $bar = split / / , $_;
push @second, $bar;
}
my %first = @first;
my %second = @second;
将第一个文件的哈希值设置为%first,将第二个文件构建为%second,第一列为键,第二列为值。
for(keys %first)
{
print $second{$_} if exists $second{$_}
}
我无法检查它,因为我在移动设备上。希望能给你一个想法。
答案 1 :(得分:0)
我假设列A是有序的,并且您实际上想要将文件1中的第一个条目与文件2中的第一个条目进行比较,依此类推。
如果这是真的,那么你就拥有了你不需要的嵌套循环。简化你的最后一次:
for my $i (0..$#firstcol) {
if ( $firstcol[$i] eq $firstcol2[$i] )
{
print $secondcol2[$i];
}
}
另外,如果你完全担心文件长度不同,那么你可以调整循环:
use List::Util qw(min);
for my $i (0..min($#firstcol, $#firstcol2)) {
附加说明:您没有在第二个文件循环while ( <FILE2> )
中扼杀您的数据。这可能会在以后引入一个bug。
答案 2 :(得分:0)
如果您的文件名为file1.txt
,file2.txt
则为下一个:
use Modern::Perl;
use Path::Class;
my $files;
@{$files->{$_}} = map { [split /\s+/] } grep { !/^\s*$/ } file("file$_.txt")->slurp for (1..2);
for my $line1 (@{$files->{1}}) {
my $line2 = shift @{$files->{2}};
say $line2->[1] if ($line1->[0] eq $line2->[0]);
}
打印:
B
^
在第1列中仅等于行A
和5
没有CPAN模块 - 产生相同的结果
use strict;
use warnings;
my $files;
@{$files->{$_}} = map { [split /\s+/] } grep { !/^\s*$/ } do { local(@ARGV)="file$_.txt";<> } for (1..2);
for my $line1 (@{$files->{1}}) {
my $line2 = shift @{$files->{2}};
print $line2->[1],"\n" if ($line1->[0] eq $line2->[0]);
}