繁体   English   中英

Perl:匹配来自两个不同文件的列

[英]Perl: Matching columns from two different files

(注意:列标题用于可读性,不在实际文件中)

文件1

COLUMN1         COLUMN2   COLUMN3
AG_446337835.1  example1  grgsdt
AG_448352465.1  example2  190197
AG_449465753.1  example3  h837h8
AG_449366462.1  example4  d34tw4
AG_444725037.1  example5  f45ge4
AG_441227463.1  example6  f3fw4t
AG_449986090.1  example7  gft7r4
AG_445666926.1  example8  4vsr55
AG_441004541.1  example9  fh893b
AG_444837264.1  example0  k3883d

文件2

COLUMN1  COLUMN2
grgsdt   AAHG
h837h8   JUJN
190197   POKJ
f45ge4   DFRF
gft7r4   NNHN
d34tw4
fh893b  YUNIP
k3883d  YUNIP
f3fw4t  YUNIP
190197  YUNIP
4vsr55  GHGF

所需的输出文件

COLUMN1         COLUMN2   COLUMN3 COLUMN4 (formerly column2 from file2)
AG_446337835.1  example1  grgsdt  AAHG 
AG_448352465.1  example2  190197  POKJ  YUNIP
AG_449465753.1  example3  h837h8  JUJN
AG_449366462.1  example4  d34tw4  
AG_444725037.1  example5  f45ge4  DFRF
AG_441227463.1  example6  f3fw4t  YUNIP
AG_449986090.1  example7  gft7r4  NNHN
AG_445666926.1  example8  4vsr55  GHGF
AG_441004541.1  example9  fh893b  YUNIP
AG_444837264.1  example0  k3883d  YUNIP

我几乎不熟悉Perl(或编程一般),我想知道您是否愿意为这个问题提供建议。

本质上,文件1中的列3对应于文件2中的列1。

我想获取file1中的每一行,读取该行的第3列,在file2中搜索匹配项,如果存在匹配项,则将file1中的行与文件2中的额外列打印到新文件中(如示例中所示)输出)。

文件大小是

文件1:2GB

档案2:718MB

该脚本将在具有250GB RAM的计算机上运行,​​因此内存不是问题。

这就是我到目前为止

#!/usr/bin/perl ;
#use warnings;

use Getopt::Long qw(GetOptions);
use experimental 'smartmatch';
#Variable to store inputted text file data
my $db ;
my $db2 ;




#Open and read File one into memory
open FPIN, "file1.txt" or die "Could not open";
my @file1 = <FPIN> ;
close FPIN;

#Open and read file two into memory
open FPIN, "file2.tab" or die "Could not open";
my @file2 = <FPIN> ;
close FPIN ;




foreach (@file2)
  {
    if (/(^\w+)\t(.+)/)
      { 
        split /\t/, $2; 
        $db2->{$1}->{"geneName"} = $1 ;
        $db2->{$1}->{"protein"} = $2 ;
      }             

  }

foreach (@file1)
    {
      #if line begins with any word character tab and anything
      if (/(^\w+.\d+)\t(.+)/)
        { 
            my @fields = split /\t/, $2;
            my $refSeqID = $1;

           #assign the data in the array to variables
            my ($geneSymbol, $geneName) = @fields[0, 1];

          #Create database data structure and fill it with the info
            $db->{$2}->{"refSeqID"} = $refSeqID ;
            $db->{$2}->{"geneSymbol"} = $geneSymbol ;
            $db->{$2}->{"geneName"} = $geneName ;

       }
   }         

foreach my $id (sort keys %{$db2}) 
  {
    if ( exists $db->{$id} )
      {   
        print $db2->{$id}."\t".$db->{$id}->{$geneSymbol}."\t".$db->{$id}-> 
        {$refSeqID}."\t".$db2->{$id}->{$protein}."\n";
      }

  }

我似乎能够正确地将两个文件读入内存。 但是,我一直无法完全比较这些文件,因此我对如何处理文件感到困惑。

实际上,打印将是我需要解决的另一个问题。

这将按照您的要求

首先读取file2.txt并构建将第一列的值与第二列的值相关联的哈希%f2

之后,只需阅读file1.txt ,将其拆分为字段,然后添加另一个字段即可,该字段通过使用第三个字段的值访问哈希值而获得

我使用了autodie来节省在open调用中处理错误的麻烦。 否则一切都是标准的

更新资料

我刚刚注意到file2.txt可能会重复第1列的值,所以我更改了代码以使哈希的每个键都对应于值数组 数组中的所有值以空格分隔出现在输出的第4列中

use strict;
use warnings 'all';
use autodie;

my %f2;

{
    open my $fh, '<', 'file2.txt';
    while ( <$fh> ) {
        my ($key, $val) = split;
        $f2{$key} //= [];
        push @{ $f2{$key} }, $val if $val;
    }
}

open my $fh, '<', 'file1.txt';

while ( <$fh> ) {
    my @line = split;
    my $c4 =  $f2{$line[2]};
    push @line, $c4 ? join(' ', @$c4) : '';
    local $" = "\t";
    print "@line\n";
}

输出

AG_446337835.1  example1    grgsdt  AAHG
AG_448352465.1  example2    190197  POKJ YUNIP
AG_449465753.1  example3    h837h8  JUJN
AG_449366462.1  example4    d34tw4  
AG_444725037.1  example5    f45ge4  DFRF
AG_441227463.1  example6    f3fw4t  YUNIP
AG_449986090.1  example7    gft7r4  NNHN
AG_445666926.1  example8    4vsr55  GHGF
AG_441004541.1  example9    fh893b  YUNIP
AG_444837264.1  example0    k3883d  YUNIP

这一个左连接 关键思想是使用geneName作为哈希中的键。

#! /usr/bin/perl
use strict;
use warnings;

my %data = ();

open $a, "file1";
while (<$a>) {
    chomp;
    my @c = split;
    $data{$c[2]} = [$c[0], $c[1], $c[2]];
}

open $b, "file2";
while (<$b>) {
    chomp;
    my @c = split;
    push @{$data{$c[0]}}, exists $c[1] ? $c[1] : "";
}

print map { "@{$_}\n" } values %data;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM