Блок кода внутри регулярного выражения в то время как цикл работает, но не показывает результаты, пока не завершится вручную - PullRequest
2 голосов
/ 01 апреля 2019

Я новичок в Perl и CS в целом и просто пытаюсь написать некоторый код, связанный с биоинформатикой, для целей обучения.Я пытаюсь пройтись по текстовому файлу, чтобы найти все вхождения определенной последовательности ($ motif) с помощью простого оператора match и цикла while, программа работает нормально, когда я определяю $ motif в самом коде, но когда я использую user-вход, код внутри моего цикла while работает, но не работает должным образом, и он также не завершается, и когда я вручную завершаю его, иногда он показывает некоторые из ожидаемых результатов, а иногда все.

use strict;
use warnings;
use feature ':5.28';


print 'Enter the file name containing the sequence:';

my $filename = <>;

chomp $filename;

open(SEQ, '<', $filename)
  or die "Could not open file '$filename' $!";

$/ = ''; #to read the whole file at once as it'll stop reading only when an undefined character comes up

my $row = <SEQ>; #storing the sequence from file to a variable
chomp $row;

print "\nEnter the Motif sequence to be searched:";

my $motif = <>;
my $counter = 0;
chomp $motif;

while ($row =~ m|($motif)|g) {
    $counter++;
    print"\n";
    print "The motif's occurnce $counter ends at position ", pos$row, "\n";
}

Ожидаемый результат - список всех вхождений $ motif, но программа не завершает работу, и когда я вручную завершаю его, используя ctrl+c, он показывает первые 2-3 вхождения, и это не то время, когда я назначаю $ motifзначение в самом коде выдает сотни совпадений в одно мгновение.

Если я присваиваю последовательность файлов (в которой я ищу) переменной $row непосредственно в моем коде, то и времяцикл работает правильно, но цикл не работает нормально только тогда, когда я беру имя входного файла ($filename) и записываю его в $row и последовательность поиска ($motif) от пользователя.Назначьте любой из них внутри кода, и программа будет работать нормально.

1 Ответ

2 голосов
/ 02 апреля 2019

Вы изменили разделитель входной записи ($/) на '' (пустая строка) по сравнению со значением \ n, которое было раньше.
В этой строке: my $motif = <>; ожидается ввод, и он не закончится как обычно "enter" (\ n). Это где ваша программа "застрять". Он ждет, пока не получит значение EOF (конец файла). Вы можете использовать Ctrl + d (или Ctrl + z в окнах), чтобы передать значение EOF, чтобы программа продолжалась.

chomp также используйте его (разделитель входных записей), поэтому он тоже не будет работать должным образом (1-й чип будет работать нормально, как он был вызван до изменения).
Вы должны вернуть его первоначальное значение (еще лучше изменить его только локально). Вы также устанавливаете разделитель входной записи на пустую строку. Вам следует установить его на undef, если вы хотите прочитать файл в «режиме slurp».

Подробнее вы можете прочитать здесь: Режим slurp - чтение файла за один шаг

Простое обновление вашего кода (обязательно удалите строку $/ = '';):

my $row = '';
{
    open(my $fh, '<', $filename) or die "Could not open file '$filename' $!";
    local $/ = undef;
    $row = <$fh>;
    close $fh;
}

Хотя я бы не рекомендовал делать это таким образом ... возможно, лучше прочитать файл в массив строк и использовать более современный способ, например Path :: Tiny .

Я сделал небольшие изменения в вашем коде и успешно протестировал его с MT_mouse.txt .
Код:

#!/usr/bin/perl

use strict;
use warnings;

print 'Enter the file name containing the sequence: ';
my $filename = <>;
chomp $filename;

open(my $fh, '<', $filename) or die "Could not open file '$filename' $!";
my @file_lines = <$fh>;
close $fh;

print 'Enter the Motif sequence to be searched: ';
my $motif = <>;
chomp $motif;
print 'Read ' . scalar(@file_lines) . " lines at file: '$filename'\nmotif: '$motif'\n";

my ($line, $occurrences) = (0, 0);
foreach my $row (@file_lines) {
    $line++;
    next unless $row =~ /\Q$motif\E/;
    my @motif_index = ();
    my $position = 0;
    while((my $index = index $row, $motif, $position) >= 0) {
        push(@motif_index, $index);
        $position = $index + length $motif;
    }
    print "Motif found on row#$line\tat position(s): " . join(', ', @motif_index) . ".\n";
    $occurrences += scalar @motif_index;
}

print "\nMotif '$motif' was " . ($occurrences ? "found $occurrences times" : 'not found') . " at file: '$filename'.\n";

__END__

Выход:

Enter the file name containing the sequence: MT_mouse.txt
Enter the Motif sequence to be searched: ACCCC
Read 272 lines at file: 'MT_mouse.txt'
motif: 'ACCCC'
Motif found on row#4    at position(s): 41.
Motif found on row#9    at position(s): 19.
Motif found on row#11   at position(s): 40.
Motif found on row#23   at position(s): 8.
Motif found on row#33   at position(s): 3.
Motif found on row#59   at position(s): 1.
Motif found on row#61   at position(s): 31.
Motif found on row#65   at position(s): 37.
Motif found on row#83   at position(s): 3.
Motif found on row#98   at position(s): 22.
Motif found on row#115  at position(s): 48.
Motif found on row#122  at position(s): 26.
Motif found on row#132  at position(s): 49.
Motif found on row#133  at position(s): 36.
Motif found on row#173  at position(s): 21.
Motif found on row#183  at position(s): 21.
Motif found on row#188  at position(s): 52.
Motif found on row#199  at position(s): 7.
Motif found on row#209  at position(s): 51.
Motif found on row#228  at position(s): 28.
Motif found on row#230  at position(s): 43.
Motif found on row#247  at position(s): 45.
Motif found on row#249  at position(s): 53.
Motif found on row#269  at position(s): 11, 18, 39.

Motif 'ACCCC' was found 26 times at file: 'MT_mouse.txt'.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...