簡體   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