[英]Perl: Matching columns from two different files
(注意:列標題用於可讀性,不在實際文件中)
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
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.