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; # банан, вишня, груша, яблоко