Дефолтная переменная $_ в Perl

Все переменные в языке программирования Perl которые содержат в себе одно значение начинаются с символа доллар $. Например, можно создать переменную $str или $var.

В Perl существует специальная переменная $_. Есть много мест в языке программирования Perl где если явно не указать переменную, то будет использована переменная $_. Есть ключевые слова, которые читают значения из этой переменной, а есть такие, которые устанавливают значения в эту переменную. Но в эту переменную можно сохранить значение и самостоятельно.

Ключевые слова, которые читают значение из $_

В качестве примера ключевого слова, которое читает значение из дефолтной переменной можно привести print. Если указать print без аргументов, то на экране будет напечатано содержимое переменной $_.

▶ Run
#!/usr/bin/perl

use strict;
use warnings;

$_ = 'Hello';

print;

Сначала мы сохранили в переменной $_ строку 'Hello' (обратите внимание что мы не использовали ключевое слово my).

А дальше мы используем print, но не передаем ему никакие аргументы. При таком использовании print выведет на экран содержимое переменной $_. print; это тоже самое что и print $_;

Результат — программа выведет на экран текст Hello.

Ключевые слова print, say при использовании без аргументов используют дефолтную переменную $_. Интересно что ключевое слово warn при использовании без аргументов переменную $_ не использует.

Другой пример когда используется дефолтная переменная — это регулярные выражения. Для того чтобы применить регулярное выражение к переменной нужно написать $str =~ /.../. А если просто написать /.../, то это тоже самое что и $_ =~ /.../.

Вот небольшой пример кода:

▶ Run
#!/usr/bin/perl

use strict;
use warnings;

$_ = 'Hello';

if (/ll/) {
    print 'yes';
} else {
    print 'no';
}

Условие if (/ll/) { проверят есть ли в переменной $_ две буквы l подряд. Поскольку в строке'Hello' есть эти две буквы, то выполняется код print 'yes';, который выводит текст yes на экран.

Ключевые слова, которые помещают значение в $_

Самое часто используемое ключевое слово, которое изменяет значение переменной $_ — это foreach. Вот пример кода:

▶ Run
#!/usr/bin/perl

use strict;
use warnings;
use feature qw(say);

foreach ('one', 'two', 'three') {
    say;
}

Здесь тело цикла foreach выполняется 3 раза для каждого элемента из списка 'one', 'two', 'three'. Перед каждым выполнением тела цикла в переменную $_ помещается следующий элемент из списка. Вот так можно записать этот цикл с явным указанием что значение нужно размещать в переменную $_: foreach $_ ('one', 'two', 'three') {

А дальше мы используем say; что тоже самое что и say $_;.

Другой способ разместить значение в переменную $_ это использовать while (<>) {. Вот код:

#!/usr/bin/perl

while (<>) {
    print " * $_";
}

Этот код читает содержимое STDIN и выводит каждую строку как markdown список. Вот пример как работать с этим кодом в консоли:

$ perl -e 'print "1\n2\n3\n"' | perl script.pl
 * 1
 * 2
 * 3

Сначала мы использовали perl однострочник, который выводит три строчки, в каждой строке цифра. А дальше мы перенаправили этот вывод на ввод скрипта, который мы только что написали. Тело цикла while (<>) { выполняется для каждой строки из ввода и эта строка помещается в переменной $_.

Пример

Вот еще один пример кода в котором активно используется дефолтная переменная $_:

▶ Run
#!/usr/bin/perl

use Data::Dumper;

my @arr = map { ucfirst } grep { /^.{3}\z/ } ('one', 'two', 'three');

print Dumper \@arr;

Если запустить эту программу, то на экране появится:

$VAR1 = [
          'One',
          'Two'
        ];

Итак, что здесь происходит. Выражение в котором происходит присвоение значений массиву @arr нужно читать справа налево.

  • Сначала мы определили список из трех строк ('one', 'two', 'three')
  • Дальше мы использовали ключевое слово grep к этому списку. grep размещает каждый элемент из первоначального списка в переменную $_ и выполняет проверку, которая записана в фигурных скобках. Если эта проверка возвращает истину, то grep возвращает значение cписка. В этом примере в фигурных скобках содержится регулярное выражение, которое применяется к дефолтной переменной. Это регулярному выражению удовлетворяют только строки которые состоят ровно из трех символов. Результат работы grep — это список уже из двух строк ('one', 'two').
  • Список из двух элементов попадет в map. Это ключевое слово размещает каждый элемент списка в дефолтную переменную и выполняет код, который написан в фигурных скобках. Результат который возвращает код является элементом списка, который возвращает map. В данном примере мы используем функцию lcfirst, которая возвращает строку у которой первый символ переведен в верхний регистр. Если этой функции не указать аргумент, то она работает с дефолтной переменной.

Официальная документация

Вот фрагмент вывода команды perldoc perlvar про переменную $_:

    $_      The default input and pattern-searching space. The following
            pairs are equivalent:

                while (<>) {...}    # equivalent only in while!
                while (defined($_ = <>)) {...}

                /^Subject:/
                $_ =~ /^Subject:/

                tr/a-z/A-Z/
                $_ =~ tr/a-z/A-Z/

                chomp
                chomp($_)

            Here are the places where Perl will assume $_ even if you don't
            use it:

            *  The following functions use $_ as a default argument:

               abs, alarm, chomp, chop, chr, chroot, cos, defined, eval,
               evalbytes, exp, fc, glob, hex, int, lc, lcfirst, length, log,
               lstat, mkdir, oct, ord, pos, print, printf, quotemeta,
               readlink, readpipe, ref, require, reverse (in scalar context
               only), rmdir, say, sin, split (for its second argument),
               sqrt, stat, study, uc, ucfirst, unlink, unpack.

            *  All file tests ("-f", "-d") except for "-t", which defaults
               to STDIN. See "-X" in perlfunc

            *  The pattern matching operations "m//", "s///" and "tr///"
               (aka "y///") when used without an "=~" operator.

            *  The default iterator variable in a "foreach" loop if no other
               variable is supplied.

            *  The implicit iterator variable in the "grep()" and "map()"
               functions.

            *  The implicit variable of "given()".

            *  The default place to put the next value or input record when
               a "", "readline", "readdir" or "each" operation's result
               is tested by itself as the sole criterion of a "while" test.
               Outside a "while" test, this will not happen.

            $_ is a global variable.

            However, between perl v5.10.0 and v5.24.0, it could be used
            lexically by writing "my $_". Making $_ refer to the global $_
            in the same scope was then possible with "our $_". This
            experimental feature was removed and is now a fatal error, but
            you may encounter it in older code.

            Mnemonic: underline is understood in certain operations.

Связанные темы

Другие статьи

Комментарии