使用Perl

时间:2015-10-25 05:34:20

标签: perl text-processing

我有三个文件,我需要将文件1的第一列与文件2的第一列匹配,然后将文件1的第二列与文件3的第一列相匹配。

文件1:
fji01dde AIDJFMGKG
dlp02sle VMCFIJGM
cmr03lsp CKEIFJ
等等...

文件2:
fji01dde 25 30
dlp02sle 40 50
cmr03lsp 60 70
等等...

文件3:
AIDJFMGKG
CKEIFJ

输出需要:
fji01dde AIDJFMGKG 25 30
cmr03lsp CKEIFJ 60 70
等等...

我只想要所有三个文件中常见的行。

以下代码会产生以下输出:
AIDJFMGKG
CKEIFJ
fji01dde 25
dlp02sle 40
cmr03lsp 60

#!/usr/bin/env perl
use strict;
use warnings;
my %data;

while (<>) {  
    my ( $key, $value ) = split;  
    push( @{ $data{$key} }, $value );  
}  

foreach my $key ( sort keys %data ) {  
    if ( @{ $data{$key} } >= @ARGV ) {  
    print join( "\t", $key, @{ $data{$key} } ), "\n";  
    }  
}

有什么想法吗?提前谢谢!

1 个答案:

答案 0 :(得分:0)

好的,看着它 - 你的问题是split - 因为默认情况下,它会在空格上分割。你的第二个文件有三个字段,而不是两个。

但是 - 你实际上并没有交叉提出同样的事情,所以你的while ( <> ) {循环不会起作用。

  • 在文件1中 - 您要检查
  • 在file2中,您正在检查密钥(并附加值)。
  • 在file3中,您没有任何价值,只有一把钥匙。

考虑到这一点:

#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;

#read file1 into a hash - but invert is it's value => key instead:
#          'CKEIFJ' => 'cmr03lsp',
# etc.  
open( my $file1, '<', "file1.txt" ) or die $!;
my %file1_content = map { reverse split } <$file1>;
close($file1);

print Dumper \%file1_content;

#read file 2 - read keys, store the values. 
#split _2_ fields, so we keep both numbers as a substring:
#e.g.:
#          'cmr03lsp' => '60 70
#',

open( my $file2, '<', "file2.txt" ) or die $!;
my %file2_content = map { split( " ", $_, 2 ) } <$file2>;
close($file2);

print Dumper \%file2_content;    

#then iterate file 3, checking if:
#file1 has a matching 'key' (but inverted - as a value) 
#file2 has a cross reference. 
open( my $file3, '<', "file3.txt" ) or die $!;
while ( my $line = <$file3> ) {
    chomp $line;
    if (    $file1_content{$line}
        and $file2_content{ $file1_content{$line} } )
    {
        print
            "$file1_content{$line} $line $file2_content{$file1_content{$line}}";
    }
}
close($file3);

打印(不包括“转储器”输出):

fji01dde AIDJFMGKG 25 30
cmr03lsp CKEIFJ 60 70
  

当我运行此代码时,我收到一条错误消息:“第10行的哈希分配中奇数个元素。”此外,这些文件中的列由制表符分隔。

不是您没有的样本数据。但是 - 是的 - 如果你的第一个文件每行有两个以上的单词,就会发生这种情况。

您可以将该循环展开为while循环:

while ( <$file1> ) { 
    my @fields = split; 
    warn "Too many fields on line $. \n" if @fields > 2; 
    $file1_data{$fields[1]} = $fields[0];
}