Интересные примеры на Perl
28 октября 2009
Около месяца собирал разные «хаки» на языке программирования Perl. Эта подборка наглядно демонстрирует, как в Perl одна-две строчки кода могут сделать больше, чем десять строк в каком-нибудь другом языке программирования.
Дополнение: См также Основы программирования на Perl.
1. Проверить, существует ли элемент (первый аргумент функции, передается по значению) в массиве (второй аргумент функции, передается по ссылке).
grep {$_ == $_[0]} @{$_[1]}; # важно: для строк использовать eq
}
2. Удалить из массива @arr элементы, которые есть в массиве @skip.
my $t = $_;
! grep { $_ == $t } @skip; # важно: для строк использовать eq
} @arr;
3. Скрипт замены строк в тексте.
while(<>) {
chomp;
last if($_ eq "==end==");
/^([^=]*)=(.*)$/ and $r{$1} = $2;
}
$d = join '', <>;
$d =~ s/$_/$r{$_}/g for (keys %r);
print $d;
4. Вывести список имен файлов и каталогов в заданной директории, отсортированный по дате последнего доступа. Обычно глобы сортируют список по имени файлов и каталогов. Для сортировки по дате последнего изменения, заменить цифру 8 на 9.
5. Удалить повторяющиеся элементы в массиве.
@links = grep { ! $cnt{$_}++; } @links;
То же самое с помощью List::MoreUtils.
# ...
@links = uniq @links;
6. Перемешать элементы массива.
my $j = rand(@links);
@links[$_,$j] = @links[$j,$_];
}
Сделать то же самое с помощью List::Util.
# ...
@links = shuffle @links;
7. Выбрать случайный элемент в массиве можно как минимум двумя способами. Можно перемешать элементы, как в предыдущем примере, и выбрать нулевой, а можно в одну строчку:
8. Аналог PHP функции urlencode.
Но лучше использовать URI::Escape.
# uri_escape, uri_unescape
9. Получить все строки файла.
10. Простой многопоточный обработчик.
use strict;
use threads;
use threads::shared;
use List::Util qw/shuffle/;
use constant THREADS_NUM => 8;
my $cnt :shared = 0;
my @threads;
my @lines;
while(<>) { chomp; push @lines, $_; }
@lines = shuffle @lines;
push @threads, threads->create(\&thread_func, $_)
for(1..THREADS_NUM);
$_->join for(@threads);
sub thread_func {
my ($thid) = @_;
my $my_cnt;
while(1) {
{ lock($cnt); $my_cnt = $cnt++; }
last if($my_cnt >= @lines);
parse_line($thid, $lines[$my_cnt]);
}
}
sub parse_line {
my ($thid, $line) = @_;
print "thid = $thid, line = $line\n";
sleep(rand(3));
}
Для выполнения этого кода Perl должен быть собран с поддержкой потоков. У меня под FreeBSD этой поддержки не оказалось, а после пересборки перла потребовалось также обновить некоторые CPAN-модули. Будьте внимательны.
11. Работа с временными файлами:
# работа с временными файлами в Perl
# (c) Alexandr A Alexeev 2011 | http://eax.me/
# подробности см в 'man File::Temp'
use strict;
use File::Temp;
# сгенерировать имя временного файла в заданном каталоге
# с указанным префиксом
my $tmp_fname = File::Temp::tempnam("./tmp", "myprfx");
print "tmp_name = $tmp_fname\n";
# получить имя временного файла в каталоге /tmp
my $tmp_fname2 = tmpnam();
print "tmp_name = $tmp_fname2\n";
# получить хэндл временного файла в каталоге /tmp
my $fh = tmpfile();
close $fh;
# получить имя и хэндл временного файла
my ($th, $tname) = tmpnam();
print "tname = $tname\n";
close $th;
12. Вырезаем HTML теги + пример работы с юникодом:
use utf8;
use HTML::Entities;
# ...
utf8::decode($_);
s/<[^>]*>//g;
decode_entities($_);
utf8::encode($_);
См также HTML::Strip.
13. Кроссплатформенное считывание файла в одну строку или в массив строк.
# ...
my $data = read_file($filename);
my @lines = read_file($filename);
# удаляем символы новой строки
@lines = map { chomp; $_; } @lines;
14, 15, 16 … Coming soon?
Метки: Perl, Параллелизм и многопоточность.
Вы можете прислать свой комментарий мне на почту, или воспользоваться комментариями в Telegram-группе.