LEARN X · ЗА 15 МИН

Perl

Весь Perl на одной странице: скаляры, массивы, хеши, регулярки, ссылки, файлы и идиомы — в комментариях к рабочему коду.

Perl за 15 минут — весь язык одной страницей. Почти без прозы: всё объяснение живёт в комментариях к рабочему коду. Perl создан Ларри Уоллом в 1987 году как «швейцарский нож» для обработки текста; его девиз — TMTOWTDI («есть больше одного способа сделать это»).

1. Структура и вывод

#!/usr/bin/perl
# Однострочный комментарий начинается с #

use strict;    # запрещает необъявленные переменные и опечатки — ВСЕГДА включай
use warnings;  # предупреждает о подозрительных конструкциях — тоже всегда

print "Привет, мир!\n";   # print не добавляет перевод строки сам — ставим \n

use feature 'say';         # включаем say (есть начиная с Perl 5.10)
say "Привет, мир!";        # say = print + \n автоматически

=pod
Так выглядит многострочный комментарий (POD-блок).
Всё от =pod до =cut игнорируется интерпретатором.
=cut

2. Скаляры

Скаляр — одно значение: число, строка или ссылка. Имя начинается с $.

my $age   = 42;          # целое число
my $pi    = 3.14;        # дробное
my $name  = 'Алиса';     # строка в одинарных кавычках — БЕЗ интерполяции
my $greet = "Привет";    # строка в двойных кавычках — С интерполяцией

# Интерполяция переменных работает только в "двойных" кавычках:
say "$greet, $name!";    # Привет, Алиса!
say '$greet, $name!';    # $greet, $name!   (одинарные печатают буквально)

# Числа и строки конвертируются автоматически по контексту:
say 5 + "3 яблока";      # 8   (строка превращается в число 3)
say "abc" . "def";       # abcdef   (. — конкатенация строк)
say "=" x 10;            # ==========   (x повторяет строку)

my $undef;               # неинициализированная переменная = undef
say "пусто" unless defined $undef;   # пусто

3. Массивы

Массив — упорядоченный список скаляров. Имя начинается с @, но элемент берётся через $.

my @fruits = ('яблоко', 'банан', 'вишня');

say $fruits[0];          # яблоко   (индекс с 0, у элемента префикс $!)
say $fruits[-1];         # вишня    (отрицательный индекс — с конца)
say scalar @fruits;      # 3        (массив в скалярном контексте = длина)
say $#fruits;            # 2        (индекс последнего элемента)

push    @fruits, 'дыня'; # добавить в конец
my $last  = pop @fruits; # снять с конца   -> 'дыня'
unshift @fruits, 'киви'; # добавить в начало
my $first = shift @fruits;   # снять с начала  -> 'киви'

my @nums = (5, 2, 9, 1);
my @slice = @nums[1, 3];         # срез: (2, 1)
my @sorted_num = sort { $a <=> $b } @nums;  # числовая сортировка: 1 2 5 9
my @sorted_str = sort @fruits;             # строковая сортировка
my @rev = reverse @nums;                   # 1 9 2 5
say "@fruits";           # элементы через пробел (интерполяция массива)

4. Хеши

Хеш — неупорядоченный набор пар «ключ → значение». Имя начинается с %.

my %age = (
    'Алиса' => 30,       # => (fat comma) автоматически берёт левый ключ в кавычки
    'Боб'   => 25,
);

say $age{'Алиса'};       # 30   (доступ к элементу: $hash{ключ})
$age{'Ева'} = 28;        # добавить/изменить пару

my @names  = keys   %age;    # список ключей (порядок не гарантирован)
my @values = values %age;    # список значений

for my $name (sort keys %age) {
    say "$name -> $age{$name}";
}

say 'есть Боб'   if exists $age{'Боб'};   # exists — проверка наличия ключа
delete $age{'Боб'};                       # удалить пару

while (my ($k, $v) = each %age) {         # each отдаёт пары по одной
    say "$k = $v";
}

5. Операторы и условия

У Perl разные операторы для чисел и для строк — это частый источник багов.

# Числовые:  ==  !=  <  >  <=  >=  <=>
# Строковые: eq  ne  lt  gt  le  ge  cmp
say 'равно'   if 5 == 5.0;        # числовое сравнение
say 'равно'   if 'abc' eq 'abc';  # строковое сравнение
say 10 == 10.0 ? 'да' : 'нет';    # тернарный оператор: да

my $score = 75;
if    ($score >= 90) { say 'отлично' }
elsif ($score >= 60) { say 'нормально' }   # elsif — слитно!
else                 { say 'плохо' }

unless ($score > 100) { say 'в пределах нормы' }  # unless = if (НЕ условие)

# Логические: && || !  и их «низкоприоритетные» близнецы and or not
my $x = 0 || 'дефолт';        # дефолт   (0 ложно)
my $y = 0 // 'дефолт';        # дефолт   (// срабатывает только на undef)

6. Циклы

# C-style for
for (my $i = 0; $i < 3; $i++) { say $i }   # 0 1 2

# foreach по списку (for и foreach — синонимы)
foreach my $f ('a', 'b', 'c') { say $f }
for my $n (1 .. 5) { say $n }              # 1..5 — диапазон

my $i = 0;
while ($i < 3)  { say $i; $i++ }           # пока истинно
until ($i >= 6) { say $i; $i++ }           # until = while (НЕ условие)

# Постфиксные модификаторы — идиоматичный Perl, без скобок и фигурных:
say $_ for 1 .. 3;                  # $_ — переменная цикла по умолчанию
say 'много' if @fruits > 1;
print "$_ " foreach reverse 1 .. 3;   # 3 2 1

last if $i > 100;   # last — выйти из цикла (как break)
next if $i % 2;     # next — к следующей итерации (как continue)

7. Регулярные выражения

Регулярки встроены в синтаксис языка — это главная сила Perl.

my $text = 'Телефон: 123-456-7890';

# =~ привязывает регулярку к строке; m// — поиск совпадения
if ($text =~ m/(\d{3})-(\d{3})-(\d{4})/) {
    say "Код: $1";        # $1, $2... — захваченные группы скобок
    say "Полностью: $&"; # $& — всё совпадение
}

my $s = 'привет мир';
$s =~ s/мир/Perl/;        # s/// — замена: 'привет Perl'
(my $copy = $s) =~ s/и/И/g;   # /g — глобально, все вхождения

my $upper = 'hello';
$upper =~ tr/a-z/A-Z/;    # tr/// — посимвольная транслитерация -> HELLO
my $count = ($text =~ tr/0-9//);   # tr в подсчёте: сколько цифр

# Модификаторы: /i регистронезависимо, /x пробелы-комментарии, /m многострочно
say 'есть' if 'ПРИВЕТ' =~ /привет/i;

# Извлечь все совпадения списком (контекст списка + /g):
my @digits = ('a1b2c3' =~ /(\d)/g);   # (1, 2, 3)

8. Функции (подпрограммы)

Аргументы приходят в специальный массив @_.

sub greet {
    my ($name) = @_;        # распаковка аргументов из @_
    return "Привет, $name!";
}
say greet('Мир');           # Привет, Мир!

sub sum {
    my $total = 0;
    $total += $_ for @_;    # @_ содержит ВСЕ переданные аргументы
    return $total;
}
say sum(1, 2, 3, 4);        # 10

# Возврат списка и его распаковка:
sub minmax {
    my @sorted = sort { $a <=> $b } @_;
    return ($sorted[0], $sorted[-1]);
}
my ($min, $max) = minmax(7, 2, 9);   # 2 и 9

9. Контекст

Одно и то же выражение даёт разный результат в скалярном и списочном контексте.

my @arr = (10, 20, 30);

my $count = @arr;        # скалярный контекст -> 3 (длина массива)
my ($a, $b) = @arr;      # списочный контекст -> 10 и 20
say "в массиве @arr элементов: " . scalar(@arr);   # scalar форсирует контекст

# wantarray внутри функции говорит, в каком контексте её вызвали:
sub context {
    return wantarray ? ('список') : 'скаляр';
}
my @l = context();   # 'список'
my $s = context();   # 'скаляр'

# localtime — классический пример контекстной функции:
my $str  = localtime;        # скаляр -> строка с датой
my @time = localtime;        # список -> (сек, мин, час, ...)

10. Ссылки

Ссылка (\) — скаляр, указывающий на другую структуру. Так строят вложенные данные.

my @arr  = (1, 2, 3);
my $aref = \@arr;            # ссылка на массив
say $$aref[0];              # 1   (разыменование через $$)
say ${$aref}[0];            # 1   (то же, явно)
say $aref->[0];             # 1   (стрелочная нотация — самая читаемая)
say "@$aref";               # 1 2 3   (разыменовать весь массив)

my %h    = (a => 1);
my $href = \%h;             # ссылка на хеш
say $href->{a};             # 1

# Анонимные структуры: [] для массива, {} для хеша
my $data = {
    name  => 'Алиса',
    langs => ['Perl', 'Python'],   # массив внутри хеша
};
say $data->{name};                  # Алиса
say $data->{langs}[0];              # Perl   (стрелку между [] и {} можно опускать)

my $code = sub { $_[0] * 2 };       # ссылка на анонимную функцию
say $code->(21);                    # 42

11. Работа с файлами

# open(дескриптор, режим, имя); проверяем результат через or die
open(my $fh, '>', 'out.txt') or die "Не открыть: $!";   # '>' — запись
print $fh "строка 1\n";
say   $fh "строка 2";
close($fh);

open(my $in, '<', 'out.txt') or die "Не открыть: $!";   # '<' — чтение
while (my $line = <$in>) {     # <$in> читает по одной строке
    chomp $line;              # chomp убирает завершающий \n
    say "прочитано: $line";
}
close($in);

# Прочитать весь файл в массив (каждая строка — элемент):
open(my $f, '<', 'out.txt') or die $!;
my @lines = <$f>;             # списочный контекст -> все строки сразу
close($f);

open(my $app, '>>', 'out.txt') or die $!;   # '>>' — дозапись в конец
print $app "ещё строка\n";
close($app);

12. Идиомы Perl

Функциональные конструкции, ради которых Perl и любят за обработку данных.

my @nums = (1, 2, 3, 4, 5, 6);

# map — преобразовать каждый элемент ($_ — текущий)
my @squares = map { $_ * $_ } @nums;        # (1, 4, 9, 16, 25, 36)

# grep — отфильтровать по условию
my @even = grep { $_ % 2 == 0 } @nums;      # (2, 4, 6)

# sort с блоком: $a и $b — сравниваемые элементы
my @desc = sort { $b <=> $a } @nums;        # по убыванию: 6 5 4 3 2 1

# Сортировка хеша по значению:
my %score = (Алиса => 90, Боб => 75, Ева => 85);
my @ranked = sort { $score{$b} <=> $score{$a} } keys %score;
say "@ranked";   # Алиса Ева Боб

# Цепочка: возвести в квадрат и оставить большие 10
my @r = grep { $_ > 10 } map { $_ * $_ } @nums;   # (16, 25, 36)

# here-doc — многострочная строка с интерполяцией
my $name = 'мир';
my $html = <<"END";
Привет, $name!
Это несколько
строк текста.
END
print $html;

# Идиома Шварца и швейцарский нож в одну строку (one-liner-стиль):
my @words = qw(груша яблоко вишня банан);   # qw() — список слов без кавычек
say join ', ', sort @words;                  # банан, вишня, груша, яблоко
Поддержать проект