Perl алмазный оператор в двойном цикле пока висит - PullRequest
0 голосов
/ 18 ноября 2018

В моем скрипте Perl у меня есть двойной бесконечный цикл while. Я читаю строки из файла с оператором diamond. Но каким-то образом, если мой скрипт достигает последней строки файла, он не возвращает undef, а зависает навсегда.

Если я уменьшу код до одного цикла while, этого не произойдет. Поэтому мне интересно, делаю ли я что-то не так или это известное ограничение языка. (На самом деле это мой первый Perl-скрипт.)

Ниже мой сценарий. Он предназначен для подсчета размера последовательностей ДНК в файлах fasta, но поведение зависания можно наблюдать с любым другим файлом с несколькими строками текста.

Версия Perl 5.18.2

Вызывается из командной строки, как perl script.pl file.fa

$l = <>;
while (1) {
    $N = 0;
    while (1) {
        print "Get line";
        $l = <>;
        print "Got line";
        if (not($l)) {
            last;
        }
        if ($l =~ /^>/) {
            last;
        }

        $N += length($l);
    }
    print $N;
    if (not($N)) {
        last;
    }
}

Я поместил некоторые отладочные операторы печати, чтобы вы могли видеть, что последней напечатанной строкой является «Получить строку», а затем она зависает.

1 Ответ

0 голосов
/ 19 ноября 2018

Добро пожаловать в Perl.

Проблема с вашим кодом заключается в том, что у вас нет возможности избежать внешнего цикла.<> вернет undef, когда достигнет конца файла.В этот момент ваш внутренний цикл заканчивается, и внешний цикл отправляет его обратно. При принудительном чтении <> начинает смотреть на STDIN, который никогда не отправляет EOF, поэтому ваш цикл продолжается вечно.

Как этоэто ваш первый Perl-скрипт, я собираюсь переписать его для вас с некоторыми комментариями.Perl - фантастический язык, вы можете написать отличный код, но в основном из-за его возраста есть некоторые старые стили, которые больше не рекомендуются.

use warnings; # Warn about coding errors
use strict; # Enforce good style
use 5.010; # Enable modernish (10 year old) features

# Another option which mostly does the same as above.
# I normally do this, but it does require a non-standard CPAN library
# use Modern::Perl;

# Much better style to have the condition in the while loop
# Much clearer than having an infinite loop with break/last statements
# Also avoid $l as a variable name, it looks too much like $1
my $count = 0; # Note variable declaration, enforced by strict
while(my $line = <>) {
    if ($line =~ /^>/) {
        # End of input block, output and reset
        say $count;
        $count = 0;
    } else {
        $count += length($line);
    }
}

# Have reached the end of the input files
say $count;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...