在上一个问题之后,我有一些代码几乎可以做我打算做的事情,但并不完全。
我试图将FILE1(3750/126477等)中的每个位置与FILE2(517-1878,2156-3289等)中的每个范围进行比较。如果它落在一个范围内,我想打印位置,范围,方向,然后将FASTA序列从下一行打印到输出文件中的同一行。目前,如果多个位置位于相同的范围内,那么当我希望每个匹配包含相关的基因序列时,它会将所有位置分组到一个块中,然后才将序列包含在最后一行中。
我的FILE1示例数据:
7065_8#10 3750 - t
7065_8#10 126477 - c
7065_8#10 1200 + T
7065_8#10 3800 - t
我的FILE2示例数据:
>SAEMRSA15_00010 dnaA_chromosomal_replication_initiator_protein_DnaA 517 1878 forward
ATGTCGGAAAAAGAAATTTGGGAAAAAGTGCTTGAAATTGCTCAAGAAAAATTATCAGCTGTAAGTTACTCAACTTTCCTAAA
>SAEMRSA15_00020 dnaN_DNA_polymerase_III,_beta_chain 2156 3289 forward
ATGATGGAATTCACTATTAAAAGAGATTATTTTATTACACAATTAAATGACACATTAAAAGCTATTTCACCAAGAACAACA
>SAEMRSA15_00030 conserved_hypothetical_protein 3670 3915 forward
GTGATTATTTTGGTTCAAGAAGTTGTAGTAGAAGGAGACATTAATTTAGGTCAATTTCTAAAAACAGAAGGGATTATTGAATCTGGTGGTCAAG
我的代码:
#!/usr/bin/perl
use strict;
use warnings;
use autodie;
my $outputfile = "/Users/edwardtickle/Documents/CC22CDS.txt";
open FILE1, "/Users/edwardtickle/Documents/CC22indels.tab";
open FILE2, "/Users/edwardtickle/Documents/CC22_CDS_rmmge.aln";
open (OUTPUTFILE, ">$outputfile");
my @file1list=();
while (<FILE1>) {
if (/^\S+\s+(\d+)/) {
push @file1list, $1;
}
}
my $nextline = 0;
close FILE1;
while ( my $line = <FILE2> ) {
if ($nextline) {
print OUTPUTFILE "$line\n";
$nextline = '';
}
elsif ($line =~ /^>(\S+)\s+\S+\s+(\d+)\s+(\d+)\s+(\S+)/) {
my $cds1 = $1;
my $cds2 = $2;
my $cds3 = $3;
my $cds4 = $4;
for my $cc22 (@file1list) {
if ( $cc22 > $cds2 && $cc22 < $cds3 ) {
$nextline++;
print OUTPUTFILE "$cc22 $cds2 $cds3 $cds4\n";
}
}
}
}
close FILE2;
我的结果:
1200 517 1878 forward
ATGTCGGAAAAAGAAATTTGGGAAAAAGTGCTTGAAATTGCTCAAGAAAAATTATCAGCTGTAAGTTACTCAACTTTCCTAAA
3750 3670 3915 forward
3800 3670 3915 forward
GTGATTATTTTGGTTCAAGAAGTTGTAGTAGAAGGAGACATTAATTTAGGTCAATTTCTAAAAACAGAAGGGATTATTGAATCTGGTGGTCAAG
我想要的结果:
1200 517 1878 forward
ATGTCGGAAAAAGAAATTTGGGAAAAAGTGCTTGAAATTGCTCAAGAAAAATTATCAGCTGTAAGTTACT
3750 3670 3915 forward GTGATTATTTTGGTTCAAGAAGTTGTAGTAGAAGGAGACATTAATTTAGGTCAATTTCTAAAAACAGAAGGGATTATTGA
3800 3670 3915 forward
GTGATTATTTTGGTTCAAGAAGTTGTAGTAGAAGGAGACATTAATTTAGGTCAATTTCTAAAAACAGAAGGGATTATTGAATCTGGTGGTCAAG
我认为这是因为代码的第一部分在第二个if规则之前永远不会匹配,但我不知道如何在保持功能的同时更改顺序。
或者,有没有一种方法可以在标题匹配后打印下一行,如果它包含字母ATCG(它显然总是会)。这会让我感觉更有效,但我又不知道从哪里开始。
感谢您的帮助!
答案 0 :(得分:1)
要获得所需的结果而不过多更改现有代码,您可以在处理标题行时获取序列行:
while ( my $line = <FILE2> ) {
if ($line =~ /^>(\S+)\s+\S+\s+(\d+)\s+(\d+)\s+(\S+)/) {
my $cds1 = $1;
my $cds2 = $2;
my $cds3 = $3;
my $cds4 = $4;
# fetch the next line from the file -- i.e. the sequence
$nextline = <FILE2>;
for my $cc22 (@file1list) {
if ( $cc22 > $cds2 && $cc22 < $cds3 ) {
print "$cc22 $cds2 $cds3 $cds4 $nextline";
}
}
}
}
答案 1 :(得分:0)
您可以使用内部循环打印相同范围内的所有匹配项。
#!/usr/bin/perl
use warnings;
use strict;
open my $IND, '<', 'file1' or die $!;
my @pos;
while (<$IND>) {
push @pos, (split)[1];
}
@pos = sort { $a <=> $b } @pos;
open my $FST, '<', 'file2' or die $!;
while (<$FST>) {
next unless /^>/;
my ($from, $to, $direction) = (split)[2 .. 4];
shift @pos while $pos[0] < $from;
next if $pos[0] > $to;
my $nextline = <$FST>;
while ($pos[0] <= $to) {
print "$pos[0] $from $to $direction\n";
print $nextline;
shift @pos;
}
}