Интересные примеры на Perl

9

Около месяца собирал разные «хаки» на языке программирования Perl. Эта подборка наглядно демонстрирует, как в Perl одна-две строчки кода могут сделать больше, чем десять строк в каком-нибудь другом языке программирования.

1. Проверить, существует ли элемент (первый аргумент функции, передается по значению) в массиве (второй аргумент функции, передается по ссылке).

sub inarr {
  grep {$_ == $_[0]} @{$_[1]}; # важно: для строк использовать eq
}

2. Удалить из массива @arr элементы, которые есть в массиве @skip.

my @rslt = grep {
  my $t = $_;
  ! grep { $_ == $t } @skip; # важно: для строк использовать eq
} @arr;

3. Скрипт замены строк в тексте

1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/perl

while(<>) {
  chomp;
  last if($_ eq "==end==");
  /^([^=]*)=(.*)$/ and $r{$1} = $2;
}

$d = join '', <>;
$d =~ s/$_/$r{$_}/g for (keys %r);
print $d;

4. Вывести список имен файлов и каталогов в заданной директории, отсортированный по дате последнего доступа. Обычно глобы сортируют список по имени файлов и каталогов. Для сортировки по дате последнего изменения, заменить цифру 8 на 9.

print join "\n", sort {(stat $a)[8] <=> (stat $b)[8]} glob "./*";

5. Удалить повторяющиеся элементы в массиве.

my %cnt; # будет содержать число повторений элементов
@links = grep { ! $cnt{$_}++; } @links;

Update: Рассово верное решение:

use List::MoreUtils qw/uniq/;
# ...
@links = uniq @links;

6. Перемешать элементы массива

for(0..$#links) {
  my $j = int rand() * scalar @links;
  ($links[$_], $links[$j]) = ($links[$j], $links[$_]);
}

Update: Рассово верное решение:

use List::Util qw/shuffle/;
# ...
@links = shuffle @links;

7. Выбрать случайный элемент в массиве можно как минимум двумя способами. Можно перемешать элементы, как в предыдущем примере, и выбрать нулевой, а можно в одну строчку:

$rand = $links[int rand() * scalar @links];

Update: Более короткий и понятный, но ресурсоемкий способ:

use List::Util qw/shuffle/;
# ...
$rand = (shuffle @links)[0];

8. Аналог PHP функции urlencode.

$url =~ s/([^a-zA-Z0-9\&\?\:\;\/\=\.\,\#\-\_]{1})/sprintf("%%%02x",ord($1))/eg;

9, 10, 11 … Coming soon :)

Похожие посты:


Comments posted (9)

[...] В полученном файле произвести замену шаблонных строк на реальные данные. Сделать это можно скриптом из восьми строк кода. Смотри #3 в моей записи Интересные примеры на Perl [...]

брр
1. зачем inarr, если он полностью дублирует grep?
4. а чем не подходит ls -t ? (disclaimer: под windows установлен MSYS/MinGW, поэтому имею всё те же unix comman line tools).
5. мы строим промужуточный список, что затратно. ++$cnt{$_} for @links – и короче и экономичнее.

Спасибо за ваш комментарий.
1. для многократного использования
4. а если нужно отсортировать по другому критерию?
5. в perl, как всегда, есть много способов сделать одно и то же :)

[...] если это не bmp). Во второй – что при запросе статьи Интересные примеры на Perl был успешно выполнен dechunk и произведено сжатие html-кода [...]

Почитал Ваш пост http://habrahabr.ru/blogs/perl/80328/
Главный недостаток Perl в том, что это wtite-only язык:
http://en.wikipedia.org/wiki/Write-only_language

Просто ради интереса сделал те же задачки на Python.

#!/usr/bin/env python
# coding=utf-8

# 1. Проверить, существует ли элемент в массиве
el = 10
arr = [10, 20, 30, 40]
print el in arr

# 2. Удалить из массива arr элементы, которые есть в массиве skip
skip = [30, 40, 50, 60]
arr = [i for i in (set(arr) - set(skip))]
print arr

# 3. Скрипт замены строк в тексте
import re
p = re.compile(r'd+')
print re.sub(p, 'a number', '2 * 2 = 4')

# 4. Вывести список имен файлов и каталогов в заданной директории,
# отсортированный по дате последнего доступа.
import os
from stat import ST_ATIME
names = [(name, os.stat(name)[ST_ATIME]) for name in os.listdir('.')]
names.sort(key=lambda x: x[1])
print names

# 5. Удалить повторяющиеся элементы в массиве.
arr1 = [1, 2, 3, 1, 3]
arr2 = [i for i in set(arr1)]
print arr2

# 6. Перемешать элементы массива
import random
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
random.shuffle(a)

# 7. Выбрать случайный элемент в массиве
print random.choice(a)

# 8. Аналог PHP функции urlencode
# http://docs.python.org/library/urllib.html#urll...

Является ли Perl write-only языком – это большой вопрос. Писать плохие программы можно на любом языке (с). В частности, обфускация php или html или javascript-кода – достаточно частое явление, что не делает эти языки write-only.

За примеры на Python спасибо. Сам я на нем не пишу, но подозревал, что аналогичные задачи на Python решаются не хуже, чем на Perl. Рад, что он оправдал мои ожидания :)

На самом деле очень неоднозначные примеры.

4. Вызывать stat внутри sort{} – это не комильфо. Питоновское решение из комментария выше красивей.

5. Удалить повторяющиеся элементы в массиве.
Тут есть побочный эффект – еще и меняется порядок элементов.

6. Перемешать элементы массива. Долой велосипеды:
use List::Util;
@list = shuffle @list

7. «$rand = $links[int rand() * scalar @links];»
Ужасный код. Я давно программирую на perl, но мой взгляд споткнулся на этом выражении и вместо того, чтобы думать над общей идеей я начинаю вспоминать приоритеты операций и думать, как это варажение будет восприматься компилятором. В общем, лакончиность есть, красота не появилась (имхо).

Нет предела совершенству. Как говориться, за код, написанный пол года назад, хочется самому себе руки оторвать. Вернусь к этому посту в апреле :)

Маленькая поправочка:
# use List::Util;
use List::Util qw/shuffle/;

[...] 10.1.2010 — Xaegr Недавно натолкнулся вот на этот пост. В нём приведено несколько интересных примеров того [...]

blog comments powered by Disqus