Присвоение поиска регулярного выражения переменной: ошибка неинициализированной переменной

Я открываю файлы в каталоге, который содержит две строки последовательностей в каждом файле. Верхняя последовательность длиннее нижней, но включает нижнюю последовательность. Я хотел бы расширить нижнюю последовательность двумя боковыми буквами в каждом направлении, как только она будет найдена в верхней последовательности. Я пытаюсь сделать это путем сопоставления регулярных выражений, но получаю неинициализированную ошибку для переменной $ newsequence. Вот как выглядит типичный файл:

    >CCCCNNNNNCCCC
    NNNNN 

Я хотел бы напечатать в одном файле все последовательности в следующем формате:

    >CCCCNNNNNCCCC
    CCNNNNNCC 

Вот мой код до сих пор:

    use strict; 
    use warnings; 

    my ($directory) = @ARGV 
    my @array = glob "$directory/*"; 
    my $header; 
    my $sequence; 
    my $newsequence; 

    open(OUT, ">", "/path/to/out.txt") or die $!; 
    foreach my $file (@array){ 
        open (my $fh, $file) or die $!; 
        while (my $line = <$fh>){ 
            chomp $line; 
            if ($line =~ /^>/) { 
                $header = $line; 
            } elsif ($line =~ /^[CN]/) { 
                $sequence = $line; 
            } 
            my ($newsequence) = $header =~ /(([CN]{2})($sequence)([CN]{2}))/; 
        } 
        print OUT $header, "\n", $newsequence, "\n"; 
    } 

Как я могу улучшить свое регулярное выражение для $ newsequence, чтобы получить адекватный вывод? Благодарю.

2 ответа

Решение

Эта строка неверна:

my ($newsequence) = $header =~ /(([CN]{2})($sequence)([CN]{2}))/; 

my Ключевое слово создает новую переменную $newsequence местный while цикл, не назначая переменную в основном скрипте. Поэтому, когда вы пытаетесь написать $newsequence после завершения цикла переменная все еще неинициализирована.

Либо положить print заявление внутри while цикл или удалить my Ключевое слово в этом назначении.

Кроме того, вы должны поместить этот оператор присваивания внутри elseif блок. В противном случае вы попытаетесь использовать $sequence прежде чем назначить его. Так что все это должно выглядеть так:

foreach my $file (@array){ 
    open (my $fh, $file) or die $!; 
    while (my $line = <$fh>){ 
        chomp $line; 
        if ($line =~ /^>/) { 
            $header = $line; 
        } elsif ($line =~ /^[CN]/) { 
            $sequence = $line; 
            ($newsequence) = $header =~ /(([CN]{2})($sequence)([CN]{2}))/; 
            print OUT $header, "\n", $newsequence, "\n"; 
        } 
    } 

} 

Если ваши условия точны (каждый файл содержит только 2 строки, а последовательность всегда находится в заголовке), вы можете сделать свой код намного проще, включая регулярное выражение:

for my $file (@array) {
  open (my $fh, $file) or die $!;
  chomp ((my $header, my $sequence) = <$fh>);
  $header =~ /(..)$sequence(..)/;
  print OUT "$header\n$1$sequence$2";
}
Другие вопросы по тегам