2015-09-02 145 views
1

我在下面编写了一个脚本来分析bedtools(-tab选项,-name选项)中的两种文件格式,以便在序列匹配时组合标题。我遇到的问题是,如果序列与多个名称匹配,它只会打印与其对应的名称之一。我想知道是否有人提出了如何解决这个问题的建议。因为我想要序列和名字的位置。是否有床垫选项?foreach循环不返回预期结果

我的脚本将这两个文件存储到它们自己的散列中,然后通过它们循环,如果它们相等,则假设打印出具有适当名称的序列中的匹配项。它这样做,但如果多个序列对应于名称,它不会出错,它只是不打印它们。所以我的结论是,foreach循环以某种形式失败的语法明智,我没有注意到。有什么建议么?干杯。

采样数据:-name输出bedtools

 >sequence_a 
    AGGT 
    >sequence_b 
    AAAA 
    >sequence_c 
    CCCC 
    >sequence_d 
    AAAA 

采样数据:-Tab输出bedtools

>1-5 
    AAAA 
    >10-14 
    ACCT 
    >15-19 
    CCCC 
从脚本预期输出

>sequence_b|1-5 
    AAAA 
    >sequence_c|15-19 
    CCCC 
    >sequence_d|1-5 
    AAAA 

脚本

my %sequence; 

open(NAMES_FILE, $ARGV[0]) or die "Cannot open the file: $!"; 
my $hash_key_name; 
my $hash_value_name; 
while (my $line = <NAMES_FILE>) { 
    if ($line =~ /^>(\S+)/) { 
    $hash_key_name = $1; 
    } 
    elsif ($line =~ /\S/) { 
    chomp $line; 
    $hash_value_name = $line; 
    $sequence{$hash_key_name} = $hash_value_name; 
    } 
} 


my %sequence_2; 
open (POSITIONS_FILE, $ARGV[1]) or die "Cannot open the file: $!"; 
my $hash_key_pos; 
my $hash_value_pos; 
while (my $line2 = <POSITIONS_FILE>) { 
    if ($line2 =~ /^>(\S+)/) { 
    $hash_key_pos = $1; 
    } 
    elsif ($line2 =~ /\S/) { 
    chomp $line2; 
    $hash_value_pos = $line2; 
    $sequence_2{$hash_key_pos} = $hash_value_pos; 
    } 
} 


foreach $hash_key_pos (keys %sequence_2) { 
    foreach $hash_key_name (keys %sequence) { 
     if ($sequence{$hash_key_name} eq $sequence_2{$hash_key_pos}){ 
      print ">$hash_key_name|$hash_key_pos\n$sequence{$hash_key_name}\n"} 
    } 
} 
+0

我会想象你的散列键有问题,而不是你的语法。在每个循环中放置打印语句以查看哈希中的内容。特别是在最后一个循环中应该有一个'else'子句,并且当哈希不匹配时会显示一条警告消息。 (我会大幅度重构这段代码以减少重复次数和减少短暂变量,但这实际上超出了你的问题的范围,也取决于你想用这段代码去哪里。) – tripleee

+0

最后一个循环尤其是效率非常低。如果你有一个像'$ hash {$ key} {“name”}'和$ hash {$ key} {“pos”}''这样的所有密钥的顶级散列,它会更加简单和高效。 – tripleee

+0

我已经有了一个打印语句来检查散列内容,为了在这里发布我的脚本,我把它拿出来了。我很抱歉。 – serious

回答

1

哈希将愉快地覆盖值,只保存最新值,而不会引发错误。如果你想抓住这一点,你需要在把一个明确的检查,看是否哈希有一个值,你覆盖它之前,是这样的:

while (my $line = <NAMES_FILE>) { 
     if ($line =~ /^>(\S+)/) { 
      $hash_key_name = $1; 
     } 
     elsif ($line =~ /\S/) { 
      chomp $line; 
      $hash_value_name = $line; 
      if (defined($sequence{$hash_key_name}) && $sequence{$hash_key_name} ne $hash_value_name) { 
       die("multiple sequences match $hash_key_name: $sequence{$hash_key_name}, $hash_value_name"); 
      } 
      $sequence{$hash_key_name} = $hash_value_name; 
     } 
} 

话虽这么说,这将是你最有帮助可以提供产生您想要捕捉的错误的示例数据。它看起来好像上面的数据不应该包含这个错误。

+0

由于序列太长,我无法上传样本数据。你如何建议我向你展示样本数据? – serious

+0

我解决了我的问题!谢谢....我没有意识到很多数据实际上是重复的......所以它只给了我一个回报......让它看起来像我错过了很多! 感谢您向我展示如何在出现错误时杀死某些东西。 (你的格式比我的要好得多) – serious

+0

谢谢。有一本名为“Modern Perl”的书,现在已经是第二或第三版了,它可以帮助您快速掌握perl编程的最新技术,功能和习惯用法。 –