суббота, 21 ноября 2009 г.

Удобства perl 5.10 или Modern::Perl

Как известно в perl 5.10 появилось много всяких вкусностей:
все новые операторы доступны по-умолчанию
Пример 1:
$a = 0 unless defined $a; #раньше 
$a //= 0;
 # perl 5.10
Пример 2:
Допустим у нас есть массив 
@types = qw/type1 type2 type3/;
и необходимо проверить наличие в нем некого элемента
if (grep {$a eq $_} @types ) {}
  # раньше
if ($a ~~ @types ) {}  #  perl 5.10  (самый быстрый способ для поиска элемента в массиве)

Так же появились новые конструкции и функции - state, given/when, say. Но они доступны после use feature ':5.10';
Решение:
use Modern::Perl;
Написав это, Вы получите use strict, use warnings, use feature ':5.10' и mro c3; 

среда, 11 ноября 2009 г.

Правильное использование временной переменной в цикле foreach


Классический перловый foreach цикл:

Вариант 1:
foreach my $element ( @list ) {
    #some code    
}

Вариант 2:
my $element;
foreach $element ( @list ) {
    #some code    
}

Сравнение:
Большинство, не задумываясь, используют первый вариант... и это правильно :). Но есть "программисты-оптимизаторы", которые используют второй вариант, аргументируя это тем, что он "быстрее" (забивая на то, что они засоряют пространство имен родительского блока). Не слушайте их!!! Первый вариант на 40% быстрее!!! (в атаче бенчмарк; хотя, естественно, чистое время перебора элементов может занимать меньше 1% времени обработки элементов )
Многих этот факт может удивить но все объясняется следующим образом: перл просто не использут предварительно  объявленую вами переменную и объявляет свою с таким же именем.

Попробуйте сами:
my $element = "NOT_USED";
foreach $element ( 1..2 ) {
    #some code
}
print $element; #выведет "NOT_USED";

вторник, 20 октября 2009 г.

Подсветка ошибок при просмотре логов

Мы часто юзаюем команду tail для логов( например  tail -f file.log ) и часто не хватает подсветки строчек, которые содержат строку "error".

Пример 1.
Следующий код подсветит целую строку красным, если она содержит слово "error":
tail -f file.log | perl -pe 's/^.*error.+$/\e[1;32;41m$&\e[0m/gim'
#ключ -p обрамляет программу в while (<>) { ... print  $_}

Пример 2.
Тут строки со словами "error", "warn", "debug" будут подсвечиваться тремя разными цветами:
tail -f file.log | perl -pe 's/^.*error.+$/\e[1;32;41m$&\e[0m/gim  or s/^.*debug.+$/\e[1;33;44m$&\e[0m/gim or s/^.*warn.+$/\e[1;33;45m$&\e[0m/gmi'

я написал небольшой скриптик который подсвечивает нужные строки по шаблону.
примеры использования:
tail -f file.log | hl -p error          #подсветить ошибки
tail -f file.log | hl              # подсвечивать ошибки и варнинги
cat file.log | hl -p warn ownpattern # подсвечивать варнинги и строки содержащие  ownpattern



Скачать приложение

понедельник, 10 августа 2009 г.

Term::ANSIColor (стандартный модуль) - раскрась терминал

Очень простой стандартный модуль, который великолепно справляется со своей задачей, а именно подсветить текст необходимым Вам цветом.
За деталями лезем в  perldoc Term::ANSIColor
Пример 1.
use Term::ANSIColor;
print color 'bold blue';
print "This text is bold blue.\n";
print color 'reset';
print "This text is normal.\n";
print colored ("Yellow on magenta.\n", 'yellow on_magenta');
print "This text is normal.\n";
print colored ['yellow on_magenta'], "Yellow on magenta.\n";

Пример 2.
use Term::ANSIColor qw(:constants);
print BOLD BLUE ON_WHITE "This text will be bold blue on white background", RESET;

суббота, 25 июля 2009 г.

Сортировка Шварца

Представим, что у нас есть масив @ar , нужно получить масив @ar_new отортировав масив @ar следующим образом :
@ar_new = sort { slow_sub ($a) <=> slow_sub($b) } @ar 
Все бы хорошо но для сортировки n елементов блок сравнения будет вызван примерно n log n раз, а каждое сравнение это двойной вызов slow_sub. И в данной ситуации сортировка Шварца все решает.

@ar_new = map  { $_->[0] } 
                       sort { $a->[1] <=> $b->[1] }  
          map  { [ $_, slow_sub($_) ] } @ar;
Теперь slow_sub будет вызвана для каждого значени всего один раз.

среда, 15 июля 2009 г.

При присвоении перл возвращает переменную (вернее - lvalue), а не ее значение

Что это дает?
Пример 1.
Можно сделать замену в скопированной переменной(сохранив при этом оригинальную)
(my $new_var = $original_var)  =~ s/pattern/replacement/;

Пример 2.
Запись вида :
$a += 2;
$a *= 3;
можно заменить на :
($a += 2) *= 3;
Пример 3.
Запись вида :

if ($x) {
    $a->{key} = 1;
}else{
    $b->{key} = 1;
}

Можно заменить на : ($x ? $a : $b)->{key} = 1

ЗЫ: с это особенностью нужно быть осторожным.
Например, код:  0 ? $a = 1 : $a = 2; print $a; # выведет 2(вроде правильно)
1 ? $a = 1 : $a = 2; print $a; # выведет тоже  2. Хотя это не самый лучший  пример, в данном случае можно (и нужно) было  бы записать $a = 1? 1: 2;

пятница, 10 июля 2009 г.

Вы знаете про стандартную перловую утилиту find2perl ?!

find2perl транслирует параметры команды  "find" в перловый код,  который использует стандартный модуль  File::Find
смотреть perldoc perlutils 

Пример:
find2perl . -user root -perm 4000 -print
выдаст следующий платформонезависимый код (функция wanted нас интересует больше всего )

#здесь было начало. выполнив пример можно увидеть весь код  ;)
sub wanted {
    my ($dev,$ino,$mode,$nlink,$uid,$gid);

    (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) &&
    ($uid == $uid{'root'}) &&
    (($mode & 0777) == 04000) &&
    print("$name\n");
}