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 – это количество элементов массива.
Несколько слов о контексте: любое слово или даже предложение может быть по-разному интерпретировано в зависимости от ситуации. Варьироваться может не только интенсивность явления, но и само явление: стукнуть в аську и стукнуть в живот… Перл так же в зависимости от ситуации по-разному понимает команды. К примеру,
выведет 10 – число элементов массива @a, т.к. скаляру $a массив присваивался именно в скалярном значении (мы же не можем запихнуть в скаляр массив…). Кстати, $a и @a – абсолютно никак не связанные переменные.
@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