Разница между `$ /` и `local $ /` - PullRequest
2 голосов
/ 01 апреля 2019

Для моей программы мне нужно использовать файлы FASTA и сделать некоторые вычисления с ними.Чтобы сделать это, я использовал local $/ = "^>, чтобы сжать мой файл до строки заголовка и последовательности строк.Хотя моя программа делает то, что я хочу, почему я не могу просто использовать $/ = "^>"?Когда я попробовал, мои результаты оказались не такими, как мне было нужно, мне было интересно, почему это так.Вот мой упрощенный код:

my @array;
while(<>){
    local $/ = "^>";
    chomp;
    push (@array, $_);
    if(eof){
        for(@array){
            ...
        }
    ...
    }
    if(eof){
        @array = ();
    }

Ответы [ 3 ]

5 голосов
/ 01 апреля 2019

local $var сохраняет значение $var и добавляет директиву в стек, что приведет к восстановлению значения $var при выходе из области (даже по исключению). Это самая близкая вещь к my, которая доступна для переменных пакета.

$_ = 123;
{
   local $_ = 456;
   # $_ is 456 here.
}
# $_ is back to being 123 here.

Это полезно, чтобы избежать проблем в окружающем коде или в вызывающей программе (в случае сабвуферов).

Обратите внимание, что значение $/ соответствует символьному символу. Это не рассматривается как регулярное выражение.

Обратите внимание, что $/, по-видимому, задано без причины в коде, который вы опубликовали (если вы что-то не указали).


почему я не могу просто использовать $/ = "^>"

Тогда изменение не будет отменено в конце блока, поэтому оно повлияет на <> в условии while, а также на любой код после цикла, который выполняет чтение.


Как мне обработать файл FASTA:

my ($header, $seq);
while (1) {
   my $line = <>;
   if (!defined($line) || $line =~ /^>/) {
      work($header, $seq) if defined($header);

      last if !defined($line);

      chomp($line);
      $header = substr($line, 1);
      $seq = "";
   } else {
      chomp($line);
      $seq .= $line;
   }
}
5 голосов
/ 01 апреля 2019

local

изменяет перечисленные переменные, чтобы быть локальными для включающего блока, файла или eval.

Сохраняет значение (уже существующей) переменной, которая затем может быть изменена по желанию, и все же после выхода из области ее первоначальное значение восстанавливается.

Как таковоеон используется точно с глобальными переменными, такими как $/ - local - изменяя их, мы можем изменить их значение в той области, где нам это нужно, и не изменять ее для всей программы.

Предоставлено больше в perlsub .

То, что показано, вызывает вопросы.$/ переменная принимает строку, а не регулярное выражение;насколько я помню, эти файлы "fasta" имеют строки, начинающиеся с >, а не с ^>.Кроме того, $/ необходимо установить перед чтением строк (с <>), и я не вижу, как показанный код выполняет свои намерения.

1 голос
/ 01 апреля 2019

Ваш код использует неопределенное поведение:

Помните: значение $/ является строкой, а не регулярным выражением. awk должно быть лучше для чего-то. : -)

  • вы изменяете значение $/ внутри while (<>), которое должно повлиять на него.

Правильно будет:

my @array;
{
    local $/ = ">";
    while (<>) {
        ...
    }
}

тогда наблюдаемая разница просто исчезает, т.е. код ведет себя одинаково с local.

Но вы всегда должны использовать local для глобальных переменных, чтобы гарантировать, что исходное значение восстанавливается при выходе из области определения local.

...