3

这是对我的问题的描述:我有两个文本文件(此处$variants$annotation)。我想检查第 2 列的值是否$variants位于第 2 列和第 3 列的值之间$annotation。如果这是真的,那么$annotation应该将第 1 列中的值添加到 中的新列$variants

这就是我的示例输入文件的样子

$annotation表示一个制表符分隔的文本文件

这些值可能重叠并且无法完美排序,因为我正在使用循环基因组

C0    C1    C2   
gene1 0     100
gene2 500   1000
gene3 980   1200
gene4 1500  5

$variants表示一个制表符分隔的文本文件

C0    C1
...   5 
...   10
...   100
...   540
...   990

输出应如下所示($variants添加了另外两列)

C0    C1   C2    C3
...   5    gene1 gene4
...   10   gene1
...   100  gene1
...   540  gene2
...   990  gene2 gene3

这就是我的脚本目前的样子

my %hash1=();
while(<$annotation>){
    my @column = split(/\t/);  #split on tabs
    my $keyfield = $column[1] && $column[2]; # I need to remember values from two columns   here. How do I do that?
    }   

while(<$variants>){
    my @column=split(/\t/);  # split on tabs
    my $keyfield = $column[1];
    if ($hash1{$keyfield} >= # so the value in column[1] should be between the values from   column[1] & [2] in $annotation
        push # if true then add values from column[0] in $annotation to new column in $variants
    }

所以我最大的问题是如何使用哈希记住文件中的两个值以及如何将一个文件中的值放入另一个文件的列中。有人可以帮我解决这个问题吗?

4

2 回答 2

1

根本不需要散列。此示例期望注释是排序的并且不重叠,它也仅在应打印变体中的所有值时才有效。

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

open my $VAR, '<', 'variants' or die $!;
<$VAR>; # skip header
my ($str, $pos) = split ' ', <$VAR>;

open my $ANN, '<', 'annotation' or die $!;
<$ANN>; # skip header

while (<$ANN>) {
    my ($gene, $from, $to) = split;
    while ($from <= $pos and $pos <= $to) {
        print "$str $pos $gene\n";
        ($str, $pos) = split ' ', <$VAR> or last;
    }
}
于 2013-08-20T16:11:23.417 回答
1

如果输入文件不大,位置也不太高,可以用数组来表示所有的位置:

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

sub skip_header {
    my $FH = shift;
    <$FH>;
}


open my $ANN, '<', 'annotation' or die $!;

my $max = 0;
while (<$ANN>) {
    $_ > $max and $max = $_ for (split)[1, 2];
}
seek $ANN, 0, 0; # Rewind the file back.

my $circular;
my @genes;
while (<$ANN>) {
    my ($gene, $from, $to) = split;
    if ($from <= $to) {
        $genes[$_] .= "$gene " for $from .. $to;
    } else {
        $circular = 1;
        $genes[$_] .= "$gene " for 0 .. $to, $from .. $max + 1;
    }
}

chop @genes;

open my $VAR, '<', 'variants' or die $!;
skip_header($VAR);
while (<$VAR>) {
    next if /^\s*#/;
    chomp;
    my ($str, $pos) = split;
    $pos = $#genes if $circular and $pos > $#genes;
    print "$_ ", $genes[$pos] // q(), "\n";
}
于 2013-08-21T12:36:45.530 回答