Perl: Простые примеры

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х символов
Мне понравилась эта заметка:
Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>