Wednesday, January 18, 2012

Perl: Простые примеры http://useunix.ru/perl-prostye-primery

http://useunix.ru/perl-prostye-primery  open F, 'text.txt' or die; @t = <F>; close F; print scalar @t;
Открыли файл "text.txt" на чтение, создали дескриптор для него (F). Если не смогли – умерли :)Открой или умри! Вот так то… На самом деле это очень удобно: когда скрипт умирает, он оставляет кучу информации, с помощью которой его можно отладить, да и в целях безопасности лучше умереть, нежели исполняться чёрт знает как…
Далее прочитали файл в массив @t (разбили файл по строкам, записали каждую строку в отдельный элемент), закрыли файл, напечатали массив @t в скалярном контексте. А в скалярном контексте @t – это количество элементов массива.
Несколько слов о контексте: любое слово или даже предложение может быть по-разному интерпретировано в зависимости от ситуации. Варьироваться может не только интенсивность  явления, но и само явление: стукнуть в аську и стукнуть в живот… Перл так же в зависимости от ситуации по-разному понимает команды. К примеру,
@a = 0..9;
$a = @a;
print $a;

выведет 10 – число элементов массива @a, т.к. скаляру $a массив присваивался именно в скалярном значении (мы же не можем запихнуть в скаляр массив…). Кстати, $a и @a – абсолютно никак не связанные переменные.
Кстати, это же можно было получить так:
open F, 'text.txt' or die; while(<F>){     $n++; } close F; print $n;
Посчитаем размер файла(количество символов):
open F, 'text.txt' or die; while(<F>){     $n+=length; } close F; print $n;
Функция length в данном случае будет вычислять длину переменной по умолчанию($_), которая внутри while принимает значение очередной строки файла.
Преобразование типов происходит тоже основываясь на контексте, в котором употребляется скаляр:
$t = '123' < '9' ? 1 : 0;#сравнение чисел print "$t\n"; $t = '123' lt '9' ? 1 : 0;#сравнение строк print "$t\n";
Для обеспечения подобной гибкости перла нужны разные операторы сравнения: для строк и для чисел. > (gt), < (lt), == (eq), != (neq). Числа сравниваются привычным способом, строки – в лексикографическом порядке (как слова в словаре).
Ещё один пример работы с массивами:
@a = (1..4,6); # забили в массив цифры от 1 до 4 и 6 @b = @a[0..2]; # забили в массив @b элементы с 0 по 2 массива @a # в Си или Паскале о подобном присвоении можно только мечтать print "@b\n";  # вывели cодержимое @b, перевод строки  ($x, $y, $z) = @a[0,1]; # создали временный массив из скаляров # ему присвоили элементы @a с 0 по 1ый, иначе говоря $x = $a[0]; $y = $a[1] print "$x", "$y", "$z"; # вывели поочерёдно скаляры
Пример использования хешей:
%h = ("Lennon"=>"John","Lenin"=>"Leonid"); # забиваем хеш данными print $h{"Lennon"}, "\n"; $h{"df0"}="DF)"; # создаём элемент массива с ключом df0 и значением DF) print %h,"\n";  # выводим все элементы хеша в виде "ключ-значение\n" for(keys %h){     print "$_","-","$h{$_}\n"; }  # то же самое, только отсортировано по ключам for(sort keys %h){     print "$_","-","$h{$_}\n"; }  $h{"df01"}="DF)!"; print scalar(%h),"\n"; print values %h, "\n"; print %h, "\n";  # убеждаемся на примере, что памяти выделяется больше, чем нужно # из-за особого способа хранения хеша (строка переводится функцией # в число, а дальше уже как в обычном массиве). Перерасход памяти # составляет около 1/4 от всей. for($i=0; $i<100;$i++){     $h{$i}="$i"; }  print scalar%h,"\n"; $h1{1}='1'; $h1{01}="2";  print scalar %h1,"\n";  print $h1{1},"\n";
Классный пример применения хеша Предположим, есть у нас текст, состоящий из слов и пробелов. Требуется посчитать сколько раз каждое слово встречалось в тексте.
open f,"text.txt" or die; # открыли файл while(<f>){ # построчно читаем     @a = split/ /; # строку бьём по пробелам, слова кидаем в @a     for(@a){         $h{$_}++; # бежим по словам, увеличиваем значение по ключу слово     } }  for(sort keys %h){     print $_, "\t", $h{$_}, "\n"; # выводим отсортированное по словам     # "ключ", табуляция,"значение", перевод строки }  close f;
Новой здесь была функция split. Вкратце: split/шаблон/, строка. Шаблон описывает по каким символам или группам символов разбиваем строку. Например, split/\s/,$a – разбить скаляр $a по пробельным символам… Шаблон, по сути – регулярное выражение. Но об этом позже. В данной ситуации мы разбили $_ по пробелам.

map & grep

Мощные похожие функции. В общем виде они выглядят так:
функция {условие} массив элементов. Возвращает преобразованный массив. В случае mapбудет браться массив элементов и для каждого элемента из него будет выполняться условие. Например:
print map{$_*$_}(1, 2, 3, 4); # выведет квадраты элементов массива справа  map{$s+=$_}(1, 2, 3, 4); # накопит в $s сумму всех элементов массива справа print $s;  print map{$_=1}(1..10); # выведет 10 единиц
grep же будет "просеивать" элементы массива справа по условию. Например:
print grep{$_>0}(1,-1,0,2); # вывести все элементы больше нуля  @a=qw/aaa bbbb ccccc/; # то же самое что и @a=("aaa", "bbbb", "ccccc"); print grep{length($_)>3}@a; # вывести все элементы длиннее 3х символов

No comments:

Post a Comment