perl遇到了非常技术性的编码问题。基本上我正在寻找一些特定的DNA序列。
my $seq = '...';
my @dna = split //, $seq;
my $amount = scalar @dna;
for my $index (0 .. $amount - 1){
if ($dna[$index] eq 'A' and $dna[$index+1] eq 'T' and
$dna[$index+2] eq 'G' and $dna[$index+3] eq 'C'
) {
do {
print $dna[$index++];
} until ($dna[$index] eq 'C' and $dna[$index+1] eq 'C' and $dna[$index+2] eq'G')
}
}
问题是,“until”部分是否处于无限循环中。我得到了所有序列,但由于某种原因,直到循环不会停止循环。我试过了
until ($dna[$index] eq 'C' and $dna[$index+1] eq 'C' and $dna[$index+2] eq 'G' ){last;}
但这突破了“for”循环。 有没有办法在不破坏 for 循环的情况下突破 do-until 循环?
答案 0 :(得分:3)
my $seq = 'xxxxxATGCyyyyyCCGzzzzz'; # Ouputs ATGCyyyyy
当ATGC
后面跟CCG
后,您的代码就可以运行。
my $seq = 'xxxxxATGCyyyyy'; # Infinite loop
如果CCG
后面没有ATGC
,则会$index
越过@dna
,导致无限循环。
my $seq = 'wwwwwATGCxxxxxATGCyyyyyCCGzzzzz'; # Ouputs ATGCxxxxxATGCyyyyy and ATGCyyyyy
你开始寻找上一场比赛开始的另一场比赛,而不是结束,所以你最终可能会有重叠的比赛。部分原因是假设循环将从您更改的值$index
继续。
my $seq = '...';
my @seq = split //, $seq;
my $seq_len = @seq;
for (my $i = 0; $i < $seq_len-7; ++$i) {
if ( $seq[$i+0] eq 'A'
&& $seq[$i+1] eq 'T'
&& $seq[$i+2] eq 'G'
&& $seq[$i+3] eq 'C'
) {
my $start = $i;
$i += 4;
for (; $i < $seq_len-3; ++$i) {
if ( $seq[$i+0] eq 'C'
&& $seq[$i+1] eq 'C'
&& $seq[$i+2] eq 'G'
) {
my $end = $i;
print(join('', @seq[$start .. $end-1]), "\n");
last;
}
}
}
}
substr
简化了事情。
my $seq = '...';
my $seq_len = length($seq);
for (my $i = 0; $i < $seq_len-7; ++$i) {
if (substr($seq, $i, 4) eq 'ATGC') {
my $start = $i;
$i += 4;
for (; $i < $seq_len-3; ++$i) {
if (substr($seq, $i, 3) eq 'CCG') {
my $end = $i;
print(substr($seq, $start, $end-$start), "\n");
last;
}
}
}
}
但正则表达式只是更进一步。
my $seq = '...';
while ($seq =~ / ( ATGC .*? ) (?= CCG ) /xsg) {
print("$1\n");
}
如果您想在没有CCG
时输出字符串的剩余部分,可以使用以下内容:
my $seq = '...';
while ($seq =~ / ( ATGC (?:(?! CCG ).)* ) /xsg) {
print("$1\n");
}
答案 1 :(得分:2)
正如perlsyn
中所述对于&#34; last&#34;,你必须更精细:
LOOP: { do { last if $x = $y**2; # do something here } while $x++ <= $z; }
如果序列在CCG
之后的某个地方不包含ATGC
,则循环不会终止。将or $index == $#dna
添加到条件中。
答案 2 :(得分:0)
虽然我绝对赞同@ ikegami基于正则表达式的方法,但我们试着挽救你所拥有的东西。一些具体问题:
last
或next
循环中直接使用do {} until ()
或do {} while ()
- 这些不是while ()
或{{1} }循环,它们是until ()
构造,这些关键字不适用。有关将do
构造包装在一次性循环中以使这些关键字可行,请参阅其他一些答案。这是我对你的代码进行的修改,让它运行并清除@ ikegami的测试障碍:
do
(是的,use constant { START => 'ATGC', STOP => 'CCG' };
use constant { START_LENGTH => length(START), STOP_LENGTH => length(STOP) };
my $sequence = 'wwwwwATGCxxxxxATGCyyyyyCCGzzzzz';
my @dna = split //, $sequence;
for (my $index = 0; $index < @dna - START_LENGTH; $index++) {
if (join('', @dna[$index .. $index + START_LENGTH - 1]) eq START) {
do {
print $dna[$index++];
} until ($index > $#dna or ($index < @dna - STOP_LENGTH and join('', @dna[$index .. $index + STOP_LENGTH - 1]) eq STOP));
print("\n");
}
}
使用SO格式化程序,因为它认为它正在引入评论。我相信有人知道如何解决这个问题,并会相应地编辑这个答案。)