Заметки по книге - Программирование на Perl


Контекст вызова некоторых функций

tr>td*5
Функция Скалярный Списочный Описание Пример
if, unless, ?: + - Принудительно приводит значаение к скалярному контексту. Например удобно когда нужно приверить что массив пуст

my @arr1 = (1,2,3);
my @arr2 = ();

warn "Array arr1 is not empty" if ( @arr1 );
warn "Array arr2 is not empty" if ( @arr2 );

$ perl script.pl 
Array arr1 is not empty at script.pl line 9.
for, foreach, while, until - + Циклы все используют с списковом контексте, но если будет скалярное выражение то они воспримут как список из 1 элемента

for ( 'test' ){
    print $_;
}
$ perl script.pl 
test
given ? ?
В perl v5.22 при использовании given/when пишет given is experimental when is experimental

when X X

</details>

Типы данных

Скалярное значение

Числа


my $int = 12345;                # число
my $pi = 3.141592;              # число с остатком
my $pi_read = 3.14_15_92_65;    # Число с остатком разделеное _
my $number = 6.02e6;            # экспотенциальная запись
my $plank = .6633E-33;          # ?
my $hex = 0xffff;               # 16-ричное чило
my $bom = 0xef_bb_55;           # 16-ричное чило разделеное _
my $oct = 0751;                 # 8-рично число
my $bin = 0b0101;               # 2-чное число

Строки


my $one = "string";
my $two = 'str';
my $wrap = "wrapped 
string";

my $join = "prefix:$one\r\n"; # пример интерполяции
my $str = 'строка';
my $string = "Это $str с интерполяцией"; 
my $str2 = 'Строка без интерполяции $100';

my $q_1 = q/single-'quote'/;
my $qq_2 = qq/double-"quoted"-$two/; # Двойные кавычки поддерживают интерполяцию

my $smile = ":) -> \x{263A}"; # также есть поддержка юникода
my $ver  = v1.2.3.123; # специальные строки которые обозначают версию
my $here  = <<END;
Если текст большой
его можно записать в переменную
таким образом.
При этом сохраняться все переносы
END

Результат команд


my $exit_code = system('ls test.txt');      # код выполнения программы
my $cmd = `pwd`;                            # вывод команды

Ссылки


my @arr = (1,2,3);
my %hash = ('test', 213, 'test2', 'rwqe');
sub sub { print 1 };

my $arr_ref = \@arr;    # ссылка на именнованный массив
my $hash_ref = \%hash;  # ссылка на именнованный хеш
my $sub_ref = \⊂    # ссылка на именнованный подпрограмму

my $arr_ref2 = [1,2,3,4];           # ссылка на аннонимный массив
my $hash_ref2 = { test => 1 };      # ссылка на аннонимный хеш
my $sub_ref2 = sub { print 2 };     # ссылка на аннонимный подпрограмму

Списочное значение

Массив


my @arr = (1,2,3);

Хеш


my %hash = ('test', 213, 'test2', 'rwqe');

или


my %week = {
    'пн' => 'понедельник',
    'вт' => 'вторник',
    'ср' => 'среда',
    'чт' => 'четверг',
    'пт' => 'пятница',
    'сб' => 'суббота',
    'вс' => 'воскресенье',
};

Пример вычисления среднего

Раскрыть

#!/usr/local/bin/perl

use uni::perl       qw| :dumper |;

open my $fh, 'grades' or die "Can't open grades: $!";
binmode(STDOUT, ':utf8');

my %grades;
while ( my $line = <$fh> ){
    my ($student, $grade) = split ' ', $line;
    $grades{$student} .= $grade . ' ';
}

close $fh;

foreach my $student ( sort keys %grades ){
    my $scores = 0;
    my $total = 0;
    my @grades = split ' ', $grades{$student};

    for my $grade ( @grades ){
        $total += $grade;
        $scores++;
    }
    my $average = $total / $scores;
    print "$student: $grades{$student}\tСреднее $average\n";
}

exit;

$ cat grades 
Nol 25
Ben 76
Clementine 49
Norm 66
Chris 92
Doug 42
Carol 25
Ben 12
Clementine 0
Norm 66

$ perl ./script.pl 
Ben: 76 12  Среднее 44
Carol: 25   Среднее 25
Chris: 92   Среднее 92
Clementine: 49 0    Среднее 24.5
Doug: 42    Среднее 42
Nol: 25     Среднее 25
Norm: 66 66     Среднее 66

открытие/закрытие файла


open my $fh, "test";            # Чтение файла
open my $fh, '<', "test";       # Тоже но с указанием действия
open my $fh, '>', "test2";      # Создает и записывает в файл, если файл уже был создан - перезаписывает
open my $fh, '>>', "test3";     # Дописывает в конец файла. Также создает если его нет
open my $fh, '-|', "ls -la";    # организовать входной фильтр - TODO: разобраться
open my $fh, '|-', "ls -la";    # организовать выходной фильтр - TODO: разобраться

print $fh 1;                    # записать в файл
close $fh;                      # закрыть файл
Полный пример

cat perl/script.pl

# запись
open my $fh, '>>', 'test.txt' or die "Can't create or open file 'test.txt'";
print $fh "hello\n";
close $fh;

# чтение
open my $fh, '<', 'test.txt' or die "Can't open file 'test.txt'";
my @test = <$fh>;
print @test;
close $fh;

$ perl script.pl 
hello

Пример создания, открытие и чтение файла с кодировкой cp1251

Раскрыть

# запись
open my $fh, '>>:encoding(cp1251)', "hi2";
print $fh "Привет\n";
close $fh;

# чтение
# v1
open my $fh, '<', "hi";
print encode("utf8", decode("cp1251", <$fh>) );

# v2
open my $fh, '<:encoding(cp1251)', "hi";
print encode("utf8", <$fh> ); # принудительно энкодим чтобы не было варнинга - Wide character in print

# v3
open my $fh, '<:encoding(cp1251)', "hi";
binmode STDOUT, 'utf8'; # Указывает в какой кодировке выводить
print <$fh>;

$ perl script.pl 
Привет

Операторы

Арифметические операторы

Пример Результат Название
$a + $b Сумма $a и $b Сложение
$a - $b Разность $a и $b Вычитание
$a * $b Произведение $a и $b Умножение
$a / $b Деление $a на $b Деление
$a % $b Остаток от деления $a на $b Деление
$a ** $b $a в степени $b Возведение в степень

Строковые операторы

Пример Результат Название
$a . $b Склейка строк $a и $b Конкатенация
$a x $b Умножение строки $a в $b раз Оператор потоврения

Оператор присваивания

Пример Результат
$a = $b Присвоить $a значение $b
$a = $b + 5 Присвоить $a значение $b + 5
$a = $a * 3 Умножить $a на 3 и записать
$a *= 3 Тоже самое
$line .= "\n" Добавить в конец переменной, символ переноса строки
$fill x= 50 Умножить строку 50 раз и записать новое значение
$val ||= 2 Присвоить значение 2, если оно не истина. Пример:

        my $val = 0;
$val ||= 2;
$val ||= 4;
print $val;
$ perl script.pl 
2
            
$val //= 2 Присвоить значение 2, если оно не определено. Пример:

        my $val = 0;
$val //= 2;
$val ||= 4;
print $val;
$ perl script.pl 
4
            

Унарные операторы

Пример Результат Название
++$a, $a++ Прибавить 1 к $a Инкремент
--$a, $a-- Вычесть 1 от $a Декремент

Логические операторы

TODO

Операторы сравнения

TODO

Операторы проверки файлов

TODO

Что есть истина?

Истина это

  • Любая строка, кроме ‘’ и ‘0’, является истиной
  • Любое число, кроме 0, является истинной
  • Любая ссылка является истинной
  • Любая неопределенная величина является ложью
Примеры

print 0 ? "true\n" : "false\n";             # 0 становится строкой '0', поэтому false
print 1 ? "true\n" : "false\n";             # 1 становится строкой '1', поэтому true
print '0' ? "true\n" : "false\n";           # '0' итак строка '0', поэтому false
print 10 - 10 ? "true\n" : "false\n";       # 10 - 10 будет строка '0', поэтому false
print 0.00 ? "true\n" : "false\n";          # 0.00 становится строкой '0', поэтому false
print 0.00 ? "true\n" : "false\n";          # пустая строка, поэтому false
print '0.00' ? "true\n" : "false\n";        # строка '0.00', поэтому true
print '0.00' + 0 ? "true\n" : "false\n";    # строка '0.00' становится числом 0, поэтому false

# из той же оперы
print +'hi' ? "true\n" : "false\n";         # строка 'hi' остается без изменений, поэтому true
print 0 + 'hi' ? "true\n" : "false\n";      # в строке 'hi', впереди нет чисел, поэтому false
print 0 + '1hello, world' ? "true\n" : "false\n"; # ну т.е. если будут впереди числа то будет true

my $a = '';
print \$a ? "true\n" : "false\n";         # ссылка является истинной даже если она содержит false
print undef() ? "true\n" : "false\n";     # функция возвращает undef, поэтому false

$ perl script.pl 
false
true
false
false
false
false
true
false
true
false
true
true
false

Операторы if и unless

if

my $a = 11;
if ( $a > 10 ){
    print "a > 10\n";
}

$ perl script.pl 
a > 10

my $a = 15;
if ( $a > 15 ){
    print "a > 15\n";
} else {
    print "a < 15\n";
}

$ perl script.pl 
a < 15

my $a = 20;
if ( $a > 15 ){
    print "a > 15\n";
} elsif( $a >= 20 ) {
    print "a >= 20\n";
} else {
    print "a > 20 or a < 20\n";
}

$ perl script.pl 
a > 15
unless

my $a = 20;
unless( $a > 40 ){
    print "a < 40\n";
}

$ perl script.pl 
a < 40

given и when

Пример