В настоящее время Perl обделяется вниманием: о нём мало что и где можно услышать и увидеть. При этом Perl действительно уникальный язык программирования, который может предложить что-то новое, и особенности которого сильно выделяют его среди других. И сегодня я вам о нём поведаю, а также расскажу о его фичах с примерами его примения.

Что из себя представляет Perl?
Perl — это скриптовый язык (как Bash или Python), разработанный ещё в 1987 году Лэри Волом. Perl — динамически типизированный. По синтаксису код на нём выглядит как что‑то между Python, C, и чем‑то своим, при этом одним из его девизов является — «Здесь больше одного способа это сделать», что отражается в исключительной гибкости языка.
Пример вывода “Hello, World!”:
my $var = "World"; # Инициализация локальной переменной $var print ("Hello, $var!\n"); # Стандартный пример вывода "Hello, World!" print "Hello, $var!\n"; # Без скобочек print "Hello, ", $var, "!\n"; # В виде листа аргументов, разделённых запятой print "Hello, " . $var . "!\n"; # В виде строки, которая соединяется в одну точками printf "Hello, %s!\n", $var; # printf say "Hello, $var!"; # say - тоже самое, что и print, только с переносом строки на конце # Есть в Perl 5.10 и позднее
Пример отсчёта от 10 до 1:
# Стандартный для C for loop for (my $i = 10; $i > 0; --$i) { say $i; } # foreach по перевёрнутому массиву от 1 до 10 foreach my $i (reverse 1..10) { say $i; } # Никакой разницы между foreach и for нет for my $i (reverse 1..10) { say $i; } # Запись и вывод из дефолтного значения $_ for (reverse 1..10) { # То же самое как если бы мы записали # for my $_ (reverse 1..10) say $_; } # В одну строчку say $_ for reverse 1..10;
Кроссплатформенность и простота работы с системой.
Так как Perl изначально создавался как скриптовый язык общего назначения для Unix, на многих Unix системах он стоит по умолчанию. Можете сами проверить есть ли он у вас whereis perl.
Конечно для пользователей прекрасной и неповторимой Windows не всё так просто, но в отличие от Bash, не нужны никакие танцы с бубном для эмуляции Linux и достаточно просто cкачать интерпретатор Perl.
Perl позволяет очень просто работать с файловой системой: читать, изменять, удалять, файлы и папки, свой простой аналог функции cat или sort в Perl можно написать всего в одну строку:
# cat в одну строку, который принимает в себя любое число файлов и выводит их содержание. # Даже точка с запятой на конце не нужны потому, что в конце блока её можно не ставить. print <> # Алмазный оператор <> - это оператор ввода пользовательского выбора # Этот оператор работает следующим образом: если пользователь передал в программу файлы, # то он возвращает их содержание, если нет, то принимает ввод с консоли до тех пор пока # пользователь не вернёт end-of-file код (Сtrl-D) и возвращает введённое
print sort <> # Сортирует все строки файла и выводит их в консоль
# Аналог 'nl -b a' который нумерует все строки файла и выводит их в консоль printf "%6d $_", $. while <> # $. возвращает номер строки
Что-то подобное алмазному оператору <> на языке Perl можно написатьследующим образом:
# Сабрутина (то же самое что и функция в других языках) subr sub subr { my $ret; # Инициализация локальной переменной $ret # Если массив входных параметров программы, @ARGV, пустой, то принимать # ввод с консоли и построчно объединять его с переменной $ret if (!@ARGV) { while (my $line = <STDIN>) { $ret .= $line; } } # Если в программу передавались параметры, то поочереди открывать каждый # файл в режиме чтения и построчно записывать его содержание в $ret else { foreach my $ARG (@ARGV) { open my $fd, "<", $ARG; while (my $line = <$fd>) { $ret .= $line; } } } return $ret; } # Вызов функции print &subr
а
Можете сами попробовать создать main.pl вставить туда код и запустить:
perl main.pl PATH_TO_FILE
В Perl также просто можно вызывать системные комманды и обрабатывать их вывод, что в сочетании с непревзойдённой работой с текстом (о которой будет следующий параграф) может сильно упростить жизнь.
# Оператор `` исполняет команду и возвращает результат её вывода, когда она завершится my $ping = `ping google.com -w 2`; print $ping
# -| открывает программу на чтение вывода open( my $ping, '-|', 'ping google.com -w 2' ); # Будет выводить в консоль результат вывода команды по ходу её выполнения while my $line (<$ping>) { print $line }
Таким образом я считаю, что Perl куда проще, мощнее и гибче чем Bash, но конечно наверное болшинство знает Bash, да и его использование более распространено. Но тем не менее, если есть возможность писать скрипт на Perl, вместо того, чтобы делать это на Bash, то почему бы и нет, особенно если вы хотите, чтобы этот скрипт работал не только на Unix, но и на Windows, хотя возможно для такого бы также хорошо подошёл Python. Всё зависит от ваших целей, желаний и ограничений.
Работа с текстом
Работа с текстом - это пожалуй самая сильная сторона Perl и главный фактор послуживший его популярности, ну и причина почему я сам начал его изучать. Из‑за глубокой интеграции с regexp и тем как страшно и непонятно код на regexp может выглядеть, иногда можно услышать, что о Perl отзываются как «write only language», но это глубоко не так и даже наоборот и сейчас я докажу это вам на своём примере.
Так вот, когда я делал 3D игру с raylib, у меня появилась потребность в использовании 3D редактора карт и я нашёл TrenchBroom. Для энтити, которых можно добавлять на карту TrenchBroom использует формат .FGD, а этот формат очень специфичный, пеприятный и с ним довольно таки неудобно работать, ну и мне в любом случае прийдётся этих энтити прописывать на C/C++, поэтому зачем вообще к этому формату прикасаться? Вместо этого можно написать программу, которая принимает в себя C/C++ код в виде классов/структур и переводит его в .FGD.
То есть нужна программа которая переводит файл такого формата:
#ifndef EXAMPLE_H #define EXAMPLE_H // Example class struct Example { const char* name; int hp; // Character's health void spawn(); // Substracts damage from hp void takeDamage(int damage); }; struct Example2 { int ammount = 0; // Ammount of stuff Example2(); // Returns true if ammount is even bool isEven(); }; #endif //EXAMPLE_H
Вот в это:
@PointClass size(-16 -16 -32, 16 16 32) = Example : "Example class" [ name(string): : : "" hp(integer): : : "Character's health" ] @PointClass size(-16 -16 -32, 16 16 32) = Example2 : "" [ ammount(integer): : 0 : "Ammount of stuff" ]
Ну для начала определим как оно вообще должно из первого сделать второе:
Структуры типа
// COMMENT\n struct NAME {...};переводятся в .FGD классы формата@PointClass size(-16 -16 -32, 16 16 32) = NAME : "COMMENT" [...]при том, что комментарии опциональны.Поля структуры типа
TYPE NAME = DEFINITION; // COMMENTпереводятся в поля .FGD класса форматаNAME(TYPE): : DEFINITION : "COMMENT", при этом определения полей и комментарии опциональны.Типы int и const char* переводятся в integer и string.
Все лишние методы класса, лишние комментарии, макросы и инклюды полностью удаляются.
Перед тем как перейти к решению на Perl давайте посмотрим как можно добится подобного результата на другом языке. Тут я уточню, что кроме C/C++ больше ничего то толком и не знаю, поэтому для меня вариантов не много. Очевидно, что для текущей задачи нужно использовать регулярные выражения, а то в противном случае решение получится чрезмерно большим, некрасивым и сложным.
regex.h простой и подойдёт для валидации небольшого набора данных, к примеру IP адрес, пароль, имя пользавателя и тп., но если нужно что-то побольше, то тут его функционала уже начинает не хватать, и получайются очень длинные однострочные write only регекспы. std::regex уже получше, но с ним всё та же проблема.
Есть PCRE2 (Perl Compatable Regular Expressions), который имеет очень мощный функционал, но который требует вызова функций с кучей параметров, что создаёт много шума из-за чего его труднее воспринимать, и для маленькой програмки с одной единственной целью это уже перебор.
Пример кода из их репозитория
/* Set PCRE2_CODE_UNIT_WIDTH to indicate we will use 8-bit input. */ #define PCRE2_CODE_UNIT_WIDTH 8 #include <pcre2.h> #include <string.h> /* for strlen */ #include <stdio.h> /* for printf */ int main(int argc, char* argv[]) { if (argc != 3) { fprintf(stderr, "Usage: %s <pattern> <subject>\n", argv[0]); return 1; } const char *pattern = argv[1]; const char *subject = argv[2]; /* Compile the pattern. */ int error_number; PCRE2_SIZE error_offset; pcre2_code *re = pcre2_compile( pattern, /* the pattern */ PCRE2_ZERO_TERMINATED, /* indicates pattern is zero-terminated */ 0, /* default options */ &error_number, /* for error number */ &error_offset, /* for error offset */ NULL); /* use default compile context */ if (re == NULL) { fprintf(stderr, "Invalid pattern: %s\n", pattern); return 1; } /* Match the pattern against the subject text. */ pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(re, NULL); int rc = pcre2_match( re, /* the compiled pattern */ subject, /* the subject text */ strlen(subject), /* the length of the subject */ 0, /* start at offset 0 in the subject */ 0, /* default options */ match_data, /* block for storing the result */ NULL); /* use default match context */ /* Print the match result. */ if (rc == PCRE2_ERROR_NOMATCH) { printf("No match\n"); } else if (rc < 0) { fprintf(stderr, "Matching error\n"); } else { PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(match_data); printf("Found match: '%.*s'\n", (int)(ovector[1] - ovector[0]), subject + ovector[0]); } pcre2_match_data_free(match_data); /* Free resources */ pcre2_code_free(re); return 0; }
А вот boost/regex.hpp - это пожалуй самый лучший вариант из всех, тк совмещает в себе простоту и мощь регекспа Пёрла, никак при этом не давя на глаза.
Пример того как первый шаг конвертации мог бы выглядеть с boost/regex.hpp
#include <boost/regex.hpp> #include <fstream> #include <iterator> #include <string> int main(int argc, char **argv) { std::ifstream ifs(argv[1], std::ios::binary); std::string source((std::istreambuf_iterator<char>(ifs)) , std::istreambuf_iterator<char>()); const boost::regex re(R"((?xs) (?: \s* //\s* (?<struct_comment>[^\n]*) )? (?<struct> \s* struct\s+ (?<struct_name>\w+\d?)\s* \{ (?<struct_content>.*?) \}; ) )", boost::regex::perl); const std::string repl = R"( @PointClass size(-16 -16 -32, 16 16 32) = $+{struct_name} : "$+{struct_comment}" [ $+{struct_content} ] )"; source = boost::regex_replace( source, re, repl , boost::match_default | boost::format_perl ); std::ofstream ofs(argv[2], std::ios::binary); ofs << source; return 0; }
Результат конвертации:
#ifndef EXAMPLE_H #define EXAMPLE_H @PointClass size(-16 -16 -32, 16 16 32) = Example : "Example class" [ const char* name; int hp; // Character's health void spawn(); // Substracts damage from hp void takeDamage(int damage); ] @PointClass size(-16 -16 -32, 16 16 32) = Example2 : "" [ int ammount = 0; // Ammount of stuff Example2(); // Returns true if ammount is even bool isEven(); ] #endif //EXAMPLE_H
У питона есть модуль re тоже способный на написание понятного regex кода:
charref = re.compile(r""" &[#] # Start of a numeric entity reference ( 0[0-7]+ # Octal form | [0-9]+ # Decimal form | x[0-9a-fA-F]+ # Hexadecimal form ) ; # Trailing semicolon """, re.VERBOSE)
Ну а как бы этот конвертер выглядел на самом Perl? Как-то так, но если вкратце и с пояснениями, то так:
#!/usr/bin/env perl # Используем самую последнюю версию Perl она по деволту включает strict и warnings use v5.42; # Для корректной работы untf8 use utf8; binmode STDOUT, ':encoding(UTF-8)'; binmode STDIN, ':encoding(UTF-8)'; # Первый аргумент - C стркутура, второй - путь куда будет экспортирован конвертированный файл my $source = $ARGV[0]; my $dest = $ARGV[1]; # Чтение открытого файла open (my $source_file, '<', $source) or die "Could not open source file: $!\n"; # Соединяем все строки в одну my $source_code = join '', <$source_file>; # Заменяем структуру на .FGD $source_code =~ s{ # Необязательный комментарий к структуре (?: ^\s* //\s* (?<struct_comment>[^\n]*) )? # Блок структуры (?<struct> \s* struct\s+ (?<struct_name>\w+\d?)\s* \{ (?<struct_content>.*?) \}; ) }{\@PointClass size(-16 -16 -32, 16 16 32) = $+{struct_name} : "$+{struct_comment}" [ $+{struct_content} ] }mgxs; # m для того, чтобы $^\R были для каждой строки, а не всего файла # g для замены всех совпадений, а не только первого # x для того, чтобы regexp игнорировал пробельные символы и всё можно # было читаемо разместить # s для того, чтобы любой символ . также принимал в себя \n # Замена полей структуры на поля .FGD класса $source_code =~ s{ # Парс типа, имени, определения и комментария поля \s* (?<variable_type>[\w\s*::<>]+?)\s+ (?<var_name>\w+) (?:\s* =\s* (?<default_value>\w+?))?; (?:\s* //\s* (?<var_comment>[^\n]+))? }{ $+{var_name}($+{variable_type}): : $+{default_value} : "$+{var_comment}" }mgxs; # Удаление всех лишних строк $source_code =~ s{ ^\s* # Строки начинающиеся с #, //, заканчивающиеся с ; с возможным комментарием # и просто пустые строки ( \#.+ | //.*? | .*?; (\s*//.*)? | ) \R }{}mgx; # Переименование типов данных $source_code =~ s/\((const )?int\)/(integer)/g; $source_code =~ s/\((const )?char\*\)/(string)/g; # Запись файла open (my $dest_file, '>', $dest) or die "Could not create dest file: $!\n";
Как вы видите с Perl проще, чем в любом другом языке, писать сложные регулярные выражения, но стоит ли оно того?.. ?
Пользовательские модули CPAN
Для Perl написано очень много пользовательских модулей для самых разных задач (прямо как и для Python), но пожалуй самыми полезными из них являются Getopt::Long и Pod::Usage, которые позволяют очень просто передавать параметры в программу и документировать код. Многие стандартные модули идут сразу вместе с Perl (включая те, про которые я только что рассказал), а те, что и не идут можно достаточно просто скачать. Для этого я рекомендую использовать cpanm, тогда процесс установки любого модуля упрощается до sudo cpanm MODULE. На NixOS я просто пишу такой простой шелл конфиг:
shell.nix
{ pkgs ? import <nixpkgs>{}}: let perll = with pkgs; [ perl perlnavigator ]; # А здесь сами модули perl_modules = with pkgs.perl5Packages; [ ]; in pkgs.mkShell { nativeBuildInputs = perll ++ perl_modules; }
Ну и на последок давайте я вам покажу как можно использовать всё, о чём я только что рассказал, в одном едином скрипте, который берёт список прокси серверов и пингует через них сайты:
#!/usr/bin/env perl use v5.42; use utf8; binmode STDOUT, ':encoding(UTF-8)'; binmode STDIN, ':encoding(UTF-8)'; # Подключаем пользовательске модули use Furl; use Getopt::Long; use Pod::Usage; # Задаём дефолтные значения my $help = 0; my $proxy_list = 'https://cdn.jsdelivr.net/gh/proxifly/free-proxy-list@main/proxies/all/data.txt'; my $timeout = 1; # Обрабатываем входные параметры GetOptions( 'help|?' => \$help , 'link-to-proxy|p=s' => \$proxy_list , 'timeout|t=i' => \$timeout); pod2usage(1) if $help; pod2usage(2) unless $ARGV[0]; # Открываем сайт со списком прокси и записываем все прокси в массив @proxy_list my $furl = Furl->new(timeout => 5); my @proxy_list = split( /\n/, $furl->get($proxy_list)->content ); # Записываем аргументы переданные в программу в список cайтов, которые мы будем # пинговать my @link_list = @ARGV; my %proxy_hash; my $counter = @proxy_list; foreach my $proxy (@proxy_list) { say $counter--, '..'; # Отcчёт того сколько прокси осталось foreach my $link (@link_list) { # Делаем curl запрос open my $fh, '-|', "curl -s -x GET -o /dev/null --write-out '\%{exitcode} \%{time_total}' --proxy $proxy -m $timeout $link"; while (my $line = <$fh>) { # Проверяем что запрос удался и если да, то выводим результат и # записываем его в %proxy_hash if ($line =~ /^(?<exit_code>\d+) (?<time>.+)/ and $+{exit_code} == 0 && $+{time} < $timeout) { say "$+{time} - $proxy"; $proxy_hash{$proxy} .= $+{time}; } } } } # Сортируем все прокси по времени и выводим foreach (sort {$proxy_hash{$a} <=> $proxy_hash{$b}} keys %proxy_hash) { say "$proxy_hash{$_} - $_"; } # perlpod документация __END__ =head1 SYNOPSIS main.pl [options...] <urls...> =head1 OPTIONS =over 4 =item B<-h, --help> Prints this message. =item B<-p, --link-to-proxy> <url> Link to a site from that to fetch proxy server links. Default is: https://cdn.jsdelivr.net/gh/proxifly/free-proxy-list@main/proxies/all/data.txt =item B<-t, --timeout> <seconds> Max time to wait for a responce before switching to next proxy. Default is: 1 =back =cut
Результат работы программы
% ./main.pl Usage: main.pl [options...] <urls...> % ./main.pl -h Usage: main.pl [options...] <urls...> Options: -h, --help Prints this message. -p, --link-to-proxy <url> Link to a site from that to fetch proxy server links. Default is: https://cdn.jsdelivr.net/gh/proxifly/free-proxy-list@main/proxies/al l/data.txt -t, --timeout <seconds> Max time to wait for a responce before switching to next proxy. Default is: 1 % ./main.pl -t 2 google.com 3408.. 1.499812 - socks5://72.49.49.11:31034 3407.. 3406.. 1.611254 - socks5://69.61.200.104:36181 3405.. 3404.. 3403.. 3402.. 3401.. 3400.. 3399.. ^C
Ресурсы для дальнейшего изучения
Если вас заинтересовал Perl, то я рекомендую следующие ресурсы к ознакомлению:
perldoc/perlintro - краткое введение в Perl и его возможности.
perldoc/perl - документация всего Perl.
perldoc/perlvar - $_, $., $!, $$ и тд.
perldoc/perlre - о регулярках в Perl.
PerlTutorial - простые туториалы для начинающих.
pelmaven/perl-tutuorial - блог на разные темы, знать которые может пригодиться.
metacpan - сайт с пользовательскими модулями для Perl.
Ну а также крайне особо сильно настоятельно рекомендую прочитать Learning Perl 8th Edition, очень хорошая книга 2021-ого года. Если к тому времени, как вы читаете эту статью выйдет новое издание — читайте его. Удачи!
Выводы
В процессе написания этой статьи я понял, что уникальность и особенность языка Perl, к сожалению не делает его незаменимым инструментом, а очень даже заменимым (заменимым на Python). У языка есть свои особенности, он по-своему необычен, интересен и крут, но есть ли сейчас много толка в его изучении? Ну насколько много, это вопрос хороший, но толк в этом для меня точно был.
Комментарии (92)

Emergy
20.04.2026 20:56Язык не плохой. Но только без модных фреймворков)

nuclight
20.04.2026 20:56А что такое “модные” ? Свежие? Их есть (Beekeper хоть). Популярные среди разработчиков на данном языке? Их тоже есть, Mojolicious тот же (который потом портировали на JavaScript кстати).
И да, Perl не исчерпывается вебом, вон AnyEvent достаточно популярен, хотя возрастом уже порядка двух десятилетий.

Anthony_S_Chet
20.04.2026 20:56код на нём выглядит как что‑то между Python, C, и чем‑то своим
А ничего, что Перл появился когда Питона ещё в планах не было?

unreal_undead2
20.04.2026 20:56Да, я бы скорее awk среди подобных упомянул.

allez24
20.04.2026 20:56Собственно, Ларри Уолл создал Perl именно по причине того, что ему стало не хватать возможностей grep/sed/awk при работе с текстовой информацией.

trinxery
20.04.2026 20:56Ну так написано же не "стиль создавался на основе Python", а просто сравнили. Почему бы и нет?

unreal_undead2
20.04.2026 20:56Ну так и не похоже ни разу. Во первых Python вполне читабельный, во вторых там идеологически "There should be one-- and preferably only one --obvious way to do it", что чётко противоречит первому примеру с perl.

IDDQDesnik
20.04.2026 20:56cat "test... test... test..." | perl -e '$??s:;s:s;;$?::s;;=]=>%-{<-|}<&|`{;;y; -/:-@[-`{-};`-{/" -;;s;;$_;see'

tenzink
20.04.2026 20:56В чём перлу нет равных, так это Code golf (контесты на самый короткий код). Смотришь на результат победителя и замираешь в немом изумлении

dtmse
20.04.2026 20:56Не только на самый короткий, но так же и самый запутанный, или просто визуально красивый. Классический пример - код, печатающий стихотворение "99 bottles of beer on the wall". Ключ -Mre=eval нужен для разрешения исполнения кода, внедренного в регулярные выражения, что в современных версиях perl по умолчанию отключено из соображений безопасности. Раньше он не требовался.
$ perl -Mre=eval ''=~( '(?{' .('`' |'%') .('[' ^'-') .('`' |'!') .('`' |',') .'"'. '\\$' .'==' .('[' ^'+') .('`' |'/') .('[' ^'+') .'||' .(';' &'=') .(';' &'=') .';-' .'-'. '\\$' .'=;' .('[' ^'(') .('[' ^'.') .('`' |'"') .('!' ^'+') .'_\\{' .'(\\$' .';=('. '\\$=|' ."\|".( '`'^'.' ).(('`')| '/').').' .'\\"'.+( '{'^'['). ('`'|'"') .('`'|'/' ).('['^'/') .('['^'/'). ('`'|',').( '`'|('%')). '\\".\\"'.( '['^('(')). '\\"'.('['^ '#').'!!--' .'\\$=.\\"' .('{'^'['). ('`'|'/').( '`'|"\&").( '{'^"\[").( '`'|"\"").( '`'|"\%").( '`'|"\%").( '['^(')')). '\\").\\"'. ('{'^'[').( '`'|"\/").( '`'|"\.").( '{'^"\[").( '['^"\/").( '`'|"\(").( '`'|"\%").( '{'^"\[").( '['^"\,").( '`'|"\!").( '`'|"\,").( '`'|(',')). '\\"\\}'.+( '['^"\+").( '['^"\)").( '`'|"\)").( '`'|"\.").( '['^('/')). '+_,\\",'.( '{'^('[')). ('\\$;!').( '!'^"\+").( '{'^"\/").( '`'|"\!").( '`'|"\+").( '`'|"\%").( '{'^"\[").( '`'|"\/").( '`'|"\.").( '`'|"\%").( '{'^"\[").( '`'|"\$").( '`'|"\/").( '['^"\,").( '`'|('.')). ','.(('{')^ '[').("\["^ '+').("\`"| '!').("\["^ '(').("\["^ '(').("\{"^ '[').("\`"| ')').("\["^ '/').("\{"^ '[').("\`"| '!').("\["^ ')').("\`"| '/').("\["^ '.').("\`"| '.').("\`"| '$')."\,".( '!'^('+')). '\\",_,\\"' .'!'.("\!"^ '+').("\!"^ '+').'\\"'. ('['^',').( '`'|"\(").( '`'|"\)").( '`'|"\,").( '`'|('%')). '++\\$="})' );$:=('.')^ '~';$~='@'| '(';$^=')'^ '[';$/='`';Почитать о том, как был создан этот шедевр, можно здесь
А создатель языка Larry Wall был неоднократным победителем конкурсов IOCCC, пример его кода - https://github.com/ioccc-src/winner/blob/master/1986/wall/wall.c

PjaniyAdmin
20.04.2026 20:56Помнится я выходной себе заработал, у нас был спор с начальником, что будет быстрее парсить файлы его поделка на sed или моя на Перл. Моя поделка оказалась быстрее :)

Daiichi
20.04.2026 20:56Помнится я выходной себе заработал, у нас был спор с начальником, что будет быстрее парсить файлы его поделка на sed или моя на Перл. Моя поделка оказалась быстрее :)
Мне выходной никто не дал, но я тоже удивил своего начальника, продемонстрировав ему, как скрипт на перле пережёвывает текстовые логи сквида за вчерашний день минут за десять, в то время как он заказывал утром отчёт по логам своей микрософт прокси из базы данных MS SQL и ждал до обеда, пока оснастка родит ему этот отчёт.
Начальник крайне удивился скорости работы моего скрипта, быстренько изучил регулярные выражения и сам перл и написал на нём свой парсер текстовых логов микрософт прокси и генератор отчётов по ним.
Правда, написанный им генератор работал где-то полчаса, сказывалась разница в количестве клиентов сквида и микрософтовской прокси. Но, всё равно, экономия времени по сравнению с родной оснасткой микрософт прокси оказалась просто колоссальной.

NoSkill24
20.04.2026 20:56Если скачать исходники Perl и скомпилировать, то в при компиляции будет создана miniperl - облегченная версия интерпретатора Perl. Сама она используется для дальнейшей сборки Perl. Это всего один исполняемый файл, который весит всего пару мегабайт!
Если компилировать в Windows с помощью древнего Windows Server 2003 R2 SDK, то получите файл miniperl.exe, который будет слинкован с древней версией msvcrt.dll и будет работать в любой версии Windows, начиная с XP без всяких дополнительных runtime библиотек.
Так вот, в миниперл можно пользоваться всеми возможностями языка, в нем нет только самих библиотек Perl. Сохраняется возможность работы с файловой системой, загрузка и обработка файлов регулярными выражениями, работа со стандартными потоками, базовая математика, запуск скриптов Perl без зависимостей от стандартных библиотек.
Удобно использовать как переносимый швейцаский нож для генерации кода, ресурсов, обработки текстовых файлов (напимер логов), скриптов для голого железа, систем востановления и т.д.
checkpoint
20.04.2026 20:56"Век живи, век учисть", сказал поручик. Возьмем на вооружение.

unreal_undead2
20.04.2026 20:56Ещё как вариант - busybox, который есть и под винду. Там grep/sed/awk, для мелких задач хватит. Perl хорош, когда пользуешься постоянно - иначе забываются специфические вещи типа контекстов и писать тяжело. А по awk и вспоминать особо нечего, если что по мануалу за несколько минут можно весь язык в памяти обновить )

checkpoint
20.04.2026 20:56sudo cpanm MODULEУ меня в системе (FreeBSD) нет никакого cpanm. Использую классический вариант установки модулей:
sudo perl -MCPAN -e 'install SomeModuleName'Надо заметить, что в отличии от многих популярных ныне языков программирования, CPAN - это архив с исходными кодами, а не репозиторий готовых пакетов. При выполнении команды install будет вызвана система сборки, которая создаст Makefile и запустит компиляцию C/C++ кода (если он присутствует в модуле), а результирующая библиотека (.so файл) будет установлена в дерево каталогов данной версии интерпретатора Perl. Но бывают и модули написанные чисто на Perl, они устанавливаются без компиляции.
А еще в модулях в репозитории CPAN как правило содержится вся необходимая документация и примеры использования данного модуля. Это очень удобно - открыл файл с модулем, почитал, скопировал кусочек примера к себе в программу и вперед.
На данный момент архив CPAN содержит более 220 000 модулей на все случаи жизни.

nuclight
20.04.2026 20:56Зачем -MCPAN, если можно
cpan -I -i? И установить local::lib конечно.
checkpoint
20.04.2026 20:56Этот скрипт
cpanпомимо local::lib имеет еще зависимости:use App::Cpan; use CPAN::Version;Зачем, если можно без них и встроенными средствами ?

nuclight
20.04.2026 20:56Зачем страдать “встроенными”, если можно проще? Вся мощь что перла, что фряхи - в легкой инсталляции нужных сторонних пакетов.

checkpoint
20.04.2026 20:56Зависимости следует искоренять! (с) мой.

nuclight
20.04.2026 20:56Хаха, и что вместо? Статически линковать всё в один огромный бинарь, как делают в Go или Rust? Спасибо, но нет, юниксы от этой глупости ушли еще более четверти века назад.

checkpoint
20.04.2026 20:56Хаха, и что вместо? Статически линковать всё в один огромный бинарь,
В нынешних условиях это вполне себе отличное решение. И бинарь нифига не огромный получается.

nuclight
20.04.2026 20:56Не огромный? Точно? Я вспоминаю Telegram Desktop на пару гигабайт в отладочной версии… щас уже наверняка куда больше.
Нет, не отличное это решение, а говно от кукловодов для идиотов.

tik4
20.04.2026 20:56Познакомился с Perl, когда пришлось погрузиться в тему написания скриптов для ПО Ansys CFX. А поскольку Ansys обильно скупал различные другие софты, каждый из которых поддерживал скрипты только на каком-то конкретном языке, то под капотом там собиралась знатная солянка. Поэтому в рамках одной задачи газодинамика/тепло/прочность собиралась пачка взаимосвязанных скриптов на разных языках, например Python + Perl + внутренние языки Apdl и ccl. Было весело :) Но ни до, ни после больше с Perl не встречался, видимо какая-то узкая ниша за ним осталась и все.

LorHobbit
20.04.2026 20:56Строкодробилка - вот его родная ниша, как тогда, так и сейчас. И в этом ему нет равных. Пережевать текст (например, логи, про что выше писали, но не только), выделить нужное, упорядочить - вот стихия Перла.

Q2W
20.04.2026 20:56К сожалению, из-за того, что популярность перла уходит, ресурсов на его оптимизацию мало.
Отсюда получаем то, что другие языки ускоряются, а перл больше нет =(
haqreu
20.04.2026 20:56Да какая там оптимизация с динамическим связыванием переменных. Внимание, вопрос:
Что выведет на экран следующая программа? :)#!/usr/bin/perl sub foo { print "$x, $y\n" } sub bar { local $x = 0; foo() } sub baz { local $y = 0; bar() } $x = 1337; $y = 42; foo(); bar(); baz()
nuclight
20.04.2026 20:56Для кого-то новости фрагменты из документации, которые спрашивают на собеседованиях на перловика? Хотя тащемта любой человек, использовавший
localв шелл-скриптах, поймет данный конкретный пример и без неё - а в них больше ничего и нету, в Перле же тридцать летmyесть, с котором поведение станет “ожидаемым” (это ведь был пример из разряда “смотрите как в этом языке неожиданно и неинтуитивно”, да?).
haqreu
20.04.2026 20:56Нет, пример к тому, что эффективности ожидать не приходится, когда интерпретатору нужно динамическую символьную таблицу держать.

nuclight
20.04.2026 20:56А причем тут тогда Перл? Такое будет и в любом другом динамическом языке, хоть бидоне, хоть жабаскрипте.

haqreu
20.04.2026 20:56Нет. И питон, и джаваскрипт имеют статическое (лексическое) связывание переменных: когда в какой-то функции вы пишете
x, то интерпретатор ищет такую переменную в тексте программы. Перл же ищетxв стеке вызовов. У вас не получится переписать вышеприведённый пример на питоне.
sappience
20.04.2026 20:56Так и Perl имеет lexical scope variables. И они являются предпочтительными.
localиспользуется редко, обычно все переменные определяются какmyи тогда они связаны лексически и работают быстро.

nuclight
20.04.2026 20:56Для своих задач (те же тексты) он уже хорошо оптимизирован, видел сравнение кода на Go “в лоб”, которое оказалось в примерно 40 раз медленнее перлового решения той же задачи.
oliva80
"Забытый” — это сильное преувеличение. Скорее, Perl перешёл из мейнстрима в нишевый инструмент для конкретных задач. Если 15 лет назад для задач на HP-UX на PA-RISC ты выбрал Perl и теперь у тебя куча легаси, он всё ещё твой лучший друг! Без проблем перенесёшь на любую современную платформу, сэкономив немало сил и средств.
Куча критической инфраструктуры (банки, заводы, энергетика) построена на этом "железе". Можно переписать на Python, но это X-Y месяцев работы команды, тесты, риски. А старый Perl-скрипт просто работает. И теперь твоё мудрое, принятое 15 лет назад решение, экономит компании миллионы.
DMGarikk
Он экономит миллионы, до тех пор как надо брать новых людей на поддержку этого кода..а их все меньше и меньше,
Хотя ИИ теперь есть
AnotherAnkor
Перл очень простой язык. Если человек не способен его изучить и писать на нём, у меня возникает непонимание как вообще в ит попал такой человек. Он сильно проще той же жабы.
unreal_undead2
В том то и дело, что писать просто. Читать чужой код уже сложнее )
DMGarikk
да все языки простые, сложность в том как на таком языке сложные проекты писать и поддерживать
бейсик простой язык и паскаль, слабо вам прям сейчас взять проект на полмиллиона строк кода на паскале (не object) и поддерживать? язык то простой! проще жабы!
rivo
Паскаль, а еще лучше Дельфя, вполне простой язык и достаточно безопасный. Вот если бы предлложили 0.5м строк легаси С++ я бы лично напрягся и хорошенько подумал.
DMGarikk
ага, конечно лучше, ктобы сомневался, но Делфя сложнее для освоения, давайте уж Паскаль будем рассматривать, он же проще ;)
и именно Паскаль, не object, очень простой язык, кто угодно выучит, давайте полмиллиона строк процедурного кода и вперед
я указал на то что простота языка - это ничего не значит, значит лишь то, в состоянии ли вы написать и поддерживать на нем крупный проект на таком языке, особенно если вы его не знаете и учите с нуля прямо держа проект в руках
p.s. я знаю что в перле есть ООП, я про другое сейчас
rivo
Даже незнаю какой версией пользовался TurboPascal. ООП добавили примерно в 1989 году, но я тогда его не понимал совсем. Писла в школе для друзей утилиты DOSовские для работы с дисками и всякой аппаратурой по ком порту. Самый большой проект который переделывал, какая-то файловая оболочка, 2х панельный менеджер. Встроеный ассемблер использовал. Помню что там строки безпасные, без нуль терминаторов. Енумы, запаписи и указатели строгие, не дают в ногу стрелять. Компилируется быстро, каких-то косяков не помню. Единственно много текста ввдодить, нет фигурных скобок для блоков. Еще С++ тогда считался хакерским, а Паскаль не круто было.
AnotherAnkor
В перле можно писать в ООП стиле, никаких проблем.
Паскаль отличается своей многослойностью, а так норм язык.
Я из тех, кто предпочитает использовать двухпанельники, тестовый редактор и командную строку. Меня таким сложно испугать.
DMGarikk
Чем? процедурным кодом на полмиллиона строк потому что вы двухпанельным менеджером и текстовым редактором пользуетесь?
Разговор был в начале о том что перл простой, его любой выучит
но проблема крупных проектов не в том что язык простой или сложный, а позволяет ли язык писать большие проекты и безболезненно поддерживать написанное? (как там классическая шутка про перл, когда программист который на нем пишет, не может разобрать то что он сам написал через год)
Java не просто так в энтерпрайзе поселилась, потому что проекты на ней тяжелее сломать и проще поддерживать при условии что половины документации нет, а часть разработчиков уже от старости померло
а в случае с Перлом это почти про все проекты можно сказать уже, но язык при этом не помогает
avramov
ну если быть до конца честным, то надо прямо сказать что очень мало программистов может через год разобрать то что написал на любом ЯП. особенно если писал без ТЗ и документации. Что хорошо в perl а так же в java, это автодокументация, кстати в данной статье есть её пример в коде, ну и утилитка perldoc или javadoc в помощь ;)
DMGarikk
ну я бы так не сказал... у меня два последних проекта были такие, буквально есть куча кода, обрывочные концепты бизнес логики - и это надо починить и запустить...потому что старой команды не осталось
Они оба были написаны на питоне, первый очень шакально но очень прямолинейно и хоть с какойто попыткой в архитектуру (хоть извращенную но всётаки), второй в черезчур в Java-стиле
мы без проблем всем отделом (4 разраба бэка) за полгода оба раскурили, отрефачили и вывели в прод
Забавный был опыт
И вот сейчас еще хотят такое принести, там дядька написал здоровенную систему в одно лицо...в отрыве от любых стандартов..вот впервые столкнулся с тем что проще сжечь и по новой написать, чем пытаться разобраться нафига так сделано и как это чинить теперь
==
мне вот кстати попадался такой проект на перле, там правда было мало кода, и я его на питон перетаскивал...там всё портит то что на перле всех хлебом не корми дай написать так что мозг сломать можно, хотя совсем не обязательно так делать...но блин все почемуто так делают
nuclight
Позволяет. Поддерживали. А Java не просто так в энтерпрайзе поселилась, а потому что её активно рекламировали и предназначалась она на замену C++ как более простой язык. И то сказать, уже более десяти лет ходит шутка про новый стандарты плюсов:
…и знаете, Перл гораздо читабельнее вот этого!
unreal_undead2
Так двухпанельники или командную строку? Истинные адепты командной строки презирают nc-clones.
AnotherAnkor
Я не настолько старый ) и речь про языки.
checkpoint
emacs - выбор мастеров! ;)
Все старички которых знаю, да и я сам, все пользуются либо far2l, либо mc. При этом многие в командной строке настоящие виртуозы. А еще я screen люблю, вместо этих ваших tmux. :)
unreal_undead2
Угу, но dired полноценно не освоил, хотя там по сути весь функционал nc-клонов.
LorHobbit
Ой, я вас умоляю. После разговора с такими "адептами" обычно выясняется, что для какой-то операции с файлами чуть сложнее cp или mv они используют "стандартный файловый менеджер", т.е. один из линуксовых клонов виндового проводника (а то и сам проводник, лол). Но при этом продолжают гордиться, что работают в командной строке, да.
А вот качественный двухпанельник не заменяет командную строку, а является её очень мощным усилителем и естественным дополнением. В линуксе это mc, в винде - Far. Особенно няшным mc стал, когда в нём наконец-то объединили командную строку под панелями с той, что отображалась по Ctrl+O.
unreal_undead2
Это молодёжь какая то. Я скорее про тех, кто юниксовым шеллом пользуется со времён СМ-4.
У меня оно так - но часто понимаю, что вместо шатания по панелькам лучше изначально логичнее раскидать файлы по каталогам и по максимуму скриптовать однообразные операции однострочниками. Но не получается. Сейчас вот с 9front играюсь - панелек там нет и не надо, просто полазить по каталогам и что-то позапускать можно в acme.
Astrowalk
Исповедую близкий подход (сижу в Linux с нулевого года )): никаких файловых менеджеров. Поддерживаю систему скриптов (кстати, один из них на Perl) и алиасов, работающих интуитивно (для меня), другим чудовищно). Получается довольно эффективно искать в развесистой файловой системе и на результатах поиска (кешируемого в индексном файле) выполнять без мыши операции вроде открытия файла в редакторах на нужной строке, скролла файла, копирования найденной строки или файлового пути в клипборд, мгновенного перехода в нужный каталог и т.д.
unreal_undead2
У меня дома где то с 1997ого, но всё таки досовские привычки победить не удалось )
Есть ещё альтернативная религия - Plan 9 - где, наоборот, вместе с командной строкой очень широко используется мышь, все три кнопки нужны )
funca
От рода деятельности зависит. Админы пользуются файловыми менеджерами - им часто приходится сравнивать содержимое каталогов, черрипикать отдельные файлы и т.п. Программисты больше навигируются не по каталогам, а по содержимому файлов, поэтому им проще в консоли.
Astrowalk
Это да. К тому же, когда приходится работать на чужом компьютере (через ssh, например), все нестандартные методы идут лесом.
KonstantinTokar
И на удивление часто из редакторов только vi.
unreal_undead2
Это база для сисадмина.
Хотя моя начальница на прошлой работе (она из тех, кто перфокарты использовал не только как бумажки для заметок) vi для программирования использовала сама и активно его среди молодых сотрудников пропагандировала - и народ реально пользовался. Меня из Emacs'а уже поздно было вытаскивать )
KonstantinTokar
Проблема перла в том, что там больше одного ООП стиля. И больше десяти. И каждый стиль рпзвивается и имеет несовместимые версии.
YuriPanchul
Проблема с перлом, что в нем есть неинтуитивные странности, вплоть до такого шухера что глобальные переменные $a и $b зарезервированы для сортировки. Ну и аргументы $1 $2 $3 нужно все время переназывать
nuclight
В любом практическом языке есть куча неинтуитвных странностей. Например, в Python - изучал его летом, с некоторой дичи просто остолбеневал. А зачем переназывать $1 $2 $3, если им сразу в регулярке можно дать человеческие имена?
YuriPanchul
Что вы имеете в виду? С моей точки зрения перловская передача параметров выглядит криво:
sub f {
my ($a, $b, $c) = @_;
nuclight
Так это не $1 $2, а
$_[1] $_[2]- совсем разные вещи! Ибо $1 $2 только в матчинге регэкспов, по большому счету (мы ж не в шелле). Ну и да,$_[1]будет только в каких-нибудь магических обертках, в обычных функциях назовут именами.Для
тупыхне умеющих абстрагироваться от привычек (см. ниже, и вообще привычки это плохо) из других языков - с 5.36 по умолчанию, а до того под “use feature ‘signatures’” доступен синтаксис видаНеа, это не криво, это УДОБНО. Это полный контроль над передаваемыми аргументами (чем-то напоминает Erlang), то есть можно вместо идиотизмов типа “перегрузка функций” обработать всё в одном месте: например, позволить субе быть как статической функцией, так и методом, принимать после обязательных параметров опциональный хэш в виде перечня key-value pairs, после которого опять же снова может быть что-то опциональное (которое мы просто проверим по типу концевых элементов, если они есть). То есть принимаем список и возвращаем список, наивысшая абстракция в стиле Lisp. Поэтому опытные перловики предпочитают приучиться к этому “старому” стилю, а не использовать сигнатуры “потому что стало можно”.
KonstantinTokar
Вот эти сигнатуры вбили ещё один гвоздь в крышку гроба перла. Он стал очень перегружен возможностями, и все радостно начали их использовать. Те же сигнатурес более чем функциональны, при том что без них всё работало.
nuclight
А в чем проблема? Всего лишь полмиллиона и не дельфёв, убежавших вперёд со времен моей юности, а на замороженном Паскале. Я вот работал на импортозамещении биллинга опсоса, 10 миллионов строк, из них миллион на COBOL, вот это было куда веселее!
m0tral
Это не так, синтаксис basic, pascal очень простой и понятный, как и JavaScript классический, именно поэтому на этих языках раньше и начинали обучение программированию.
С++, rust тупо не понять, если не знаешь синтаксиса
DMGarikk
Давайте по другому пример приведу
Язык 1С, там всё очень просто, даже блин по русски, синтаксис, операторы, там ПРЕДЕЛЬНО простые.
А потом откроем код большого проекта на нем написанного и попробуем разобраться.
==
еще раз, простота языка != простота разработки крупных проектов на нем