| |
Предварительные требования: знание языка С, работа в Unix, понятие о регулярных выражениях. И, естественно, темы 5 и 6 курса "Технологии Интернет".
Архивы самого языка Перл и его библиотек распространяются свободно и доступны через сайты CPAN. Библиотеки Перла называются модулями (стандартное расширение .pm), а сами программы - скриптами. И модули, и скрипты являются текстовыми файлами.
Для установки языка Перл необходимо иметь в системе компилятор С (желательно, gcc). Распаковать архив с языком (на текущий момент 27.11.99 это perl5.005_03.tar.gz). В каталоге, куда распаковался архив, выполнить следующие команды:
./configure # configure задаст много вопросов, на все можно ответить нажатием Enter (т.е. принять значение по умолчанию) make # перейти в режим суперпользователя make install
По умолчанию perl установится в /usr/local (исполнимые файлы - в /usr/local/bin/, библиотеки - в /usr/local/lib/perl5/, документы справочника man - в /usr/local/man (по самому языку) и в /usr/local/lib/perl5/5.00503/man (по библиотекам). Следует добавить соответстующие пути в переменные окружения PATH и MANPATH (в файле .profile).
Для запуска программ, написанных на Перле надо подать команду
perl имя_файла_с_программойили просто ввести имя файла с программой, если в первая строка этого файла выглядит:
#!/usr/local/bin/perl
Перл поставляется с несколькими стандартными модулями. Для работы с CGI требуется взять из CPAN и установить следующие библиотеки (в указанном порядке):
Установка каждой библиотеки производится командой
perl Makefile.PL && make && make test && make installподанной в каталоге, куда распаковаля архив библиотеки. Для выполнения последней части команды (make install) требуются привилегии суперпользователя.
Библиотеки устанавливаюися в дерево /usr/local/lib/perl5/. Документы man по установленным библиотекам находятся в /usr/local/lib/perl5/5.00503/man.
В этом разделе дана минимальная необходимая информация по тем элементам Перла, которые чаще всего используются при написании скриптов. Перл здесь рассматривается как С-подобный язык, поэтому акцентируются отличия от С. Этот раздел ни в коей мере не претендует на описание языка Перл (многие моменты сознательно опущены); для этой цели обратитесь к Camel Book, Llama Book или книге Маслова.
Комментарий "отсюда и до конца строки" - символ "#".
Переменные бывают трех типов: скаляры, списки и хэши. Описывать переменные не нужно, если только вы не используете директиву "use strict"; иначе каждая переменная должна быть описана с помощью "my имя_переменной".
Скаляры
Скаляр содержит одно значение; это может быть строка или число, Перл сам определяет тип значения по контексту проводимых со скаляром операций. Например, при попытке конкатенировать два скаляра операцией "." они будут рассмотрены как строки, а при попытке сложить их значения операцией "+" - как числа. При проведении числовых операций над строками, значение которых не может быть интерпретировано как число, числовое значение такого скаляра считается нулевым (см. также ниже п. Операторы, выражения и операции).
Повтор специально для программистов на С: строковые значения не оканчиваются на символ "\0". Строковых значений как таковых вообще не существует, строка - это один из двух способов интерепретации значения скаляра, который сам по себе ни на что особенное не заканчивается.
Имена всех скалярных переменных обязаны начинаться на $ ($x, $my_variable_1).
my $x; # $x создается, равно undef $x; # ложно defined($x); # ложно $x=0; $x; # ложно defined($x); # истинно $x=5; $x; # истинно defined($x); # истинно $x=undef; # опять undef!
Списки и массивы
Списком (list) называется упорядоченная последовательность скалярных значений; порядковые номера (индексы) начинаются с нуля. Отдельно стоящие списки заключаются в скобки:
($x, "abc", 15)Обращение к элементу списка осуществляется путем указания индекса этого элемента в квадратных скобках:
$y=($x, "abc", 15)[1]; # $y="abc"
Переменная, значением которой является список, называется массивом (array). Имена всех массивов обязаны начинаться с @ (@array). При обращении к элементу массива знак @ заменяется на $:
$array[0] $array[$x] $array[-2] # второй элемент с конца(смысл: элемент массива - это скаляр, следовательно он начинается с $). Примеры формирования массивов:
@array=($x, "abc", 15); @array=($x, $y, @another_array); @array=(); #пустой списокКоличество элементов в массиве: scalar @array (см. также п. "Контексты" ниже); индекс последнего элемента: $last_index = $#array.
Извлечение части массива:
($a, $b, $c) = @array[3,4,5]; @sublist=@array[3,4,5];Соответственно, наоборот:
@array[3,4,5]=($a,$b,"xyz");производит присвоение значений части массива @array (если элементы @array[0-2] ранее отсутствовали, они создаются со значениями undef).
Двух- и более мерные массивы в явном виде не поддерживаются.
Функции для работы с массивами:
@list = reverse @array
@list = reverse список
push @array, $x
push @array, список
$x = pop @array
$x = shift @array
unshift @array, $x
unshift @array, список
@list = splice @array, $from, $length, список
@list = splice @array, $from, $length
@list = splice @array, $from
Хэши
Переменная-хэш представляет собой массив, элементы которого индексируются строками (ассоциативный массив). Порядок хранения элементов в хэше не определен. Имена всех переменных-хэшей обязаны начинаться на % (%my_hash). При обращении к элементу списка знак % заменяется на $ и используются фигурные скобки:
$hash{"key_A"} $hash{$x}Хэши могут быть сформированы с помощью объединения четного числа скаляров в скобки:
%hash=("abc", $x, "def", 15); # $hash{abc}=$x и $hash{def}=15 #запятые для удобо читаемости могут быть заменены на "=>" %hash=("abc" => $x, "def" => 15); %hash=(); #пустой хэшВообще, любой список (массив) может быть рассмотрен в качестве хэша, т.е. %hash=@array. При этом нечетные элементы списка станут ключами хэша, а четные - соответствующими значениями. Если число элементов в списке нечетное, то последний элемент сконструированного таким образом хэша будет существовать со значением undef ("неопределенность"). Если в списке есть одинаковые элементы на нечетных позициях, то в хэш будет внесено значение, ключом которого является последний из одинаковых нечетных элементов списка.
@array=('a',1,'b',2,'c'); # для 'c' нет пары %hash=@array; # получилось: $hash{c}=undef %hash=('a' => 1, 'b' => 2, 'a' => 3); # получилось: $hash{a}=3
Верно и обратное: любой хэш может быть рассмотрен как список. Так например работает инверсия хэша с помощью функции reverse, которая принимает в качетсве аргумента список и возвращает тот же список задом наперед (см. ниже).
Функции для работы с хэшами:
@array = keys %hash
@array = values %hash
($key, $value) = each %hash
exists $hash{$key}
delete $hash{$key}
%rev_hash = reverse %hash
Операторы, выражения и операции Перла во многом аналогичны языку С. Ниже рассмотрены отличия.
Каждое выражение в Перл вычисляется в списочном, либо скалярном контексте. То есть в списочном контексте предполагается, что значение выражения должно быть списком, а в скалярном - скаляром. Контекст определяется, например, типом переменной, стоящей в левой части оператора присвоения. Многие функции определяют контекст, в котором они были вызваны и возвращают разные результаты в зависимости от контекста. Например, функция localtime (текущее местное время) в скалярном контексте возвращает строку вида "Fri Nov 26 20:36:33 1999", а в списочном контексте - список из чисел: секунды, минуты, часы, день месяца, месяц и т.д. Для того чтобы форсировать скалярный контекст, можно использовать оператор scalar.
$x = localtime; # скалярный контекст @time = localtime; # списочный контекст ($sec,$min,$hour) = localtime[0,1,2]; # списочный контекст print scalar localtime; # скалярный контекст
Значением списка в скалярном контексте является длина списка:
$x=@array; # в переменную $x помещается длина списка @arrayЗначением скаляра в списочном контексте является список, состоящий из одного этого скаляра.
Значения выражений и операции
# открыть файл myfile.txt, присвоив ему дескриптор FILE, # или выйти из программы с сообщением об ошибке open (FILE, "myfile.txt") or die ("Cannot open file"); # вывести сообщение в случае существования элемента хэша exists $hash{"mykey"} and print "My key exists!"; # присвоить переменной $x значение 5, если $x имеет неопределеное или нулевое значение $x ||= 5;
$x = "Now is " . scalar localtime; $x .= " (time is local)."; # то же что $x = $x . " (time is local).";Сравнения скаляров как строк выполняются следующими операциями:
$a eq $b | Истинно, если $a и $b одинаковы |
$a ne $b | Истинно, если $a и $b неодинаковы |
$a lt $b | Истинно, если $a раньше по алфавиту, чем $b |
$a gt $b | Истинно, если $a позже по алфавиту, чем $b |
$a le $b | Истинно, если $a раньше по алфавиту или совпадает с $b |
$a ge $b | Истинно, если $a позже по алфавиту или совпадает с $b |
$a cmp $b | -1, если $a раньше по алфавиту, чем $b; 0, если $a и $b одинаковы; 1, если $a позже по алфавиту, чем $b |
Внимание, распространенная ошибка! Операции "== != > < >= <=" выполняют сравнение скаляров как чисел. Использование их в "скалярно-строковом" контексте приведет к неверным результатам. Например, "11">"2", но "2"gt"11". Более того, $a="xyz"; $b="qwerty"; $a==$b - истинно, поскольку как числа обе этих переменных равны нулю.
# читать из файла с дексриптором FILE по одной строке (оператор <FILE>) # и удалять символ перевода строки из конца прочитанной строки (функция chomp) while ($a=<FILE>) { chomp $a; } # то же самое, используется переменная $_ while (<FILE>) { chomp; }
Операторы
if (...) {...}; условие ? выражение_да : выражение_нет ; while(...) {...}; do {...} while (...); for (...;...;...;) {...};Отличия и дополнения рассмотрены ниже.
if ($a<$b) { $a=$b; } while ($a<$b) { some_function($a); }Однако для операторов ветвления в таком случае есть сокращенная "постфиксная" форма записи:
$a=$b if ($a<$b);
print "a=",$a; НО: join ':', split ('/', $a); или join ':', split ('/'), $a;
foreach $i (@array) { print $i; } # то же самое с использованием переменной $_ foreach (@array) { print; }
# присвоить переменной $x значение 5, если $x имеет неопределеное или нулевое значение unless ($x) { $x=5; } # то же, что и $x ||= 5;Будьте внимательны при программировании сложных условий с помощью unless - помните теорему де Моргана: отрицание произведения есть сумма отрицаний; отрицание суммы есть произведение отрицаний.
until ($array[$i++] == $x) {;}соответственно и do {...} until(...).
Управление циклами:
foreach $i (@array) { next if ($i<0); $sum += $i; }
# считывать строки из файла и выводить на печать, пока не встретится пустая строка while ($a=<FILE>) { chomp $a; last unless ($a); print $a, "\n"; }
# это не самый лучший алгоритм поиска одинаковых слов в двух списках, # зато здесь используется выход сразу из двух циклов M1: foreach $i (@array1) { foreach $j (@array2) { if ( $i eq $j ) { last M1; } } }
Строковые выражения заключаются в одинарные (') или двойные (") кавычки. Везде внутри двойных кавычек производится подстановка переменных - скаляров, элементов списков и элементов хэшей; целые списки подставляются как подстрока в которой все элементы списка следуют друг за другом без разделителя; хэши целиком не подставляются. Для экранирования спецсимволов внутри двойных кавычек используется обратный слэш: \$, \@, \", \\; также распознаются все спецсимволы языка С: \n, \t и т.п.
$x="abc"; @array=('c','d','e'); %hash=( a => "A", b=> "B"); print "this is \$x: \"$x\"; \nthis is element 2 of \@array: \"$array[2]\";\n", "and \$hash{a} is \"$hash{a}\"\n"; ВЫВОД: this is $x: "abc"; this is element 2 of @array: "e"; and $hash{a} is "A"
Строки, употребляемые как ключи хэшей, если это буквальные строки без подстановок ("abc"), в кавычки можно не заключать: $hash{abc}.
Внутри одинарных кавычек никакие подстановки не производятся, спецсиволы типа "\n" не интепретируются и все символы воспринимаются буквально; исключение: комбинация \' (обратный слэш - одинарная кавычка), которая интепретируется как одинарная кавычка, являющаяся частью строки. Одинарная кавычка внутри двойных кавычек воспринимается буквально.
Регулярные выражения
Регулярные выражения (РВ) Перла - надмножество РВ grep/awk, используемых в Unix. В РВ следующие символы имеют специальное значение:
\ | ( ) [ { ^ $ * + ? . /
Символы "]" и "}" имеют специальные значения, только когда встречаются после соответственно "[" и "{". Все прочие символы в РВ воспринимаются буквально. Символ "/" имеет специальное значение не в регулярном выражении, а как признак начала и конца регулярного выражения (см. ниже примеры). Ниже кратко описаны наиболее часто используемые метасимволы РВ и их значения.
. (точка)
*
+
?
^
$
[символы] [^символы]
(РВ)
|
\s
\w
\d
\b
\S, \W, \D, \B
$переменная
\
Регулярные выражения заключаются в пару слэшей: /РВ/, после которых могут следовать модификаторы:
Обратите внимание, что метасимволы $, ^, \b не поглощают символы обрабатываемой строки, т.е. например, ^ - это не первый символ строки, а начало строки как таковое; аналогично, \b - это не первый или последний символ слова, а граница между символами типа \W и \w. Иначе говоря, слово cat соответствует РВ /^c/, а слово act ему не соответствует; или в строке "a yellow cat" регулярному выражению /\byellow\b/ соответствует подстрока "yellow", а не " yellow " или "ello".
Оператор сопоставления
Поиск РВ в строке:
$s =~ /РВ/модификаторы; $s !~ /РВ/модификаторы;Операция возвращает в скалярном контексте "Истинно", если строка $s (не) соответствует РВ, иначе возвращается "Ложно". Если $s не указано, используется $_.
if ( $d =~ /vvsu\.ru$/ ) { ... } if ( /^From: /i) { ... }
Оператор замены
Замена части строки:
$s =~ s/РВ/замена/модификаторы;Операция производит поиск подстроки строки $s, соответствующей РВ, после чего заменяет эту подстроку на замену. Если указан модификатор g, то заменяются все подстроки, соответствующие РВ, иначе заменяется только первая найденная подстрока. Операция возвращает количество произведенных замен. Если $s не указано, используется $_. Подстановку переменных можно использовать и в РВ, и в замене. В части замена можно использовать также спецсимволы $1,$2,..., которые произведут подстановку соответствующей части РВ, взятой в скобки. Примеры:
#в строке $x поменять первые два поля местами; #$1 ссылается на первое выражение в скобках в первой части оператора, $2 - на второе $x =~ s/([^ ]*) *([^ ]*)/$2 $1/; #убрать точку с конца строки $_ s/\.$//; #заменить все слова white на black в переменной $_ s/\bwhite\b/black/ig; #заменить в $_ все выражения #include_date на текущую дату #используется модификатор e, говорящий о том, #что вторая часть оператора должна быть воспринята как Перл-код s/#include_date/localtime/eg; #то же самое, но текст "#include_date" хранится в переменной $date_token s/$date_token/localtime/eg;
Чтение и запись файлов осуществляется через переменную-дескриптор файла. Имя такой переменной не имеет специального префикса и, как правило, записывается прописными буквами. Дексриптор создается при вызове функции open. Дескрипторы файлов не требуется предварительно объявлять даже при использовании "use strict".
Открытие файла
open (FILE, "filename") or die ("Cannot open filename: $!");Функция open возвращает "ложно" в случае невозможности открыть файл, в этом случае выполняется функция die, которая выводит свой аргумент на печать и завершает работу скрипта. Переменная S! - стандартная переменная Перла, содержит описание последней возникшей системной ошибки.
FILE - дескриптор файла, он будет использован ниже в операциях чтения, записи и закрытия файла.
В приведенном примере файл filename открывается для чтения. Для открытия файла на запись с нуля его имя нужно предварить символом ">" (если файл до этого существовал, его содержимое пропадет); для открытия на добавление в конец - предварить символами ">>":
open (FILE, ">filename") or die ("Cannot open filename: $!"); open (FILE, ">>filename") or die ("Cannot open filename: $!"); #открыть для чтения и записи open (FILE, "+>filename") or die ("Cannot open filename: $!");Для любого скрипта при его запуске по умолчанию открываются дескрипторы STDIN, STDOUT и STDERR.
Чтение из файла
Оператор <FILE> производит чтение из файла с дескриптором FILE. В скалярном контексте (например, в условии цикла while) оператор при кадом вызове возвращает очередную строку текста до следующего символа перевода строки включительно. В списочном контексте возвращается список всех текстовых строк от текущей позиции до конца файла.
# скалярный контекст while (<FILE>) { chomp; if ($_ eq "this text") { do_someting(); } } # списочный контекст @all_lines=<FILE>;
Внимание, распространенная ошибка! Строка, считанная из файла, скорее всего оканчивается на символ перевода строки (если только это не последняя строка в файле и при этом файл не заканчивается переводом строки). Про этот символ часто забывают и пытаются сравнивать считанное значение с неким другим значением, не содержащим, разумеется, перевода строки. Используйте функцию chomp для того, чтобы избавиться от этого символа на конце строки.
Еще одна распространенная ошибка! Оператор <> (внутри скобок пусто) считывает не из стандартного ввода, а из файлов, имена которых указанны как аргументы командной строки. При завершении одного файла ввод продолжается с начала следующего файла в том порядке, в каком имена файлов указаны в командной строке. Открывать файлы при использовании оператора <> не требуется.
Запись в файл
print FILE "эта строка печатается в FILE\n";
Закрытие файла
close FILE;Хотя при выходе из скрипта Перл и закрывает все незакрытые файлы, настоятельно рекомендуется делать это явным вызовом функции close во избежание различных побочных эффектов.
Вывод в программу
Для передачи данных в стандартный ввод другой программы нужно создать с помощью open соответствующий дескриптор файла (при этом программа будет запущена) и вывести в него данные. Для создания такого дескриптора вторым аргументом в функцию open передается путь к программе, предваренный символом "|":
open (MAIL, "|/usr/bin/mail $user") or die($!); print MAIL "Subject: Happy birthday!\n\n", "Hi, $user! Happy birthday!"; close MAIL;
Ввод из программы
Для приема данных из стандартного вывода другой программы нужно создать с помощью open соответствующий дескриптор файла (при этом программа будет запущена) и ввести из него данные. Для создания такого дескриптора вторым аргументом в функцию open передается путь к программе, после которого следует символ "|":
open (LS, "/usr/bin/ls $dir |") or die($!); @dir_listing= <LS>; close LS;
Переименование, удаление файла и изменение его атрибутов
# переименовать файл rename $oldname, $newname or die($!); # удалить файлы (возвращает количество успешно удаленных файлов) unlink $this_file, $that_file, @and_whole_list_of_files; # изменить атрибуты файлов # (возвращает количество файлов у которых атрибуты были изменены) chmod 0755, @array_of_filenames; # изменить владельцев файлов ($uid и $gid должны быть числовыми) # (возвращает количество файлов у которых владельцы были изменены) chown $uid, $gid, @array_of_filenames;Запуск другой программы
Для выполнения другой программы из скрипта используется функция system, аргументом которой является список argc[] (т.е. командная строка вывываемой программы, начинающаяся с имени самой программы).
system $program_to_run, $argument1, $argument2, ...;Функция возвращает 0 при успешном завершении вызванной программы и X*256, если статус выхода программы был X.
В этом пункте описаны некоторые полезные функции Перла для работы со строками (функции для работы с регулярными выражениями рассмотрены выше).
Разбор строки
Функция split разбивает скалярное значение, интерпретируемое как строка, на части, используя указанный разделитель, и возвращает результат в виде списка.
@список = split; @список = split разделитель; @список = split разделитель, строка; @список = split разделитель, строка, лимит;
Лимит указывает, что строка будет разбита не более, чем на лимит частей (иными словами, будут восприняты только первые лимит-1 разделителей; весь остаток будет возвращен в последнем элементе списка). Если лимит отсутствует, то все встретившиеся в строке разделители будут участвовать в разбиении.
Если строка отсутствует, обрабатывается $_.
Разделитель может быть регулярным выражением (заключается в слэши: /РВ/) или буквальной строкой (заключается в кавычки: 'строка'). Если разделитель отсутствует, то подразумевается /\s+/ ("один или более пробельных символов подряд"); т.е. split без аргументов экивалентен "split /\s+/, $_".
Пример:
# вывод списка всех пользователей системы с их идентификаторами UID open (PASSFILE, "/etc/passwd") or die($!); while (<PASSFILE>) { chomp; ($user, $junk, $uid) =split ':'; #ненужные элементы списка отбрасываются print "User $user has UID $uid\n"; };
Формирование строки из списка элементов
join
join 'разделитель', @список;
Функция join формирует скаляр-строку, состоящую из элементов списка, отделяя значения элементов друг от друга разделителем.
$_ = join ' | ', "a", "b", "c"; print; #ВЫВОД: "a | b | c" # заменить разделители с двоеточия на запятую с пробелом $_ = join ', ' (split, ':');
sprintf
Функция sprintf работает так же, как в языке С.
Поиск подстроки в строке
index
$позиция = index $строка, $подстрока, $начальная_позиция; $позиция = index $строка, $подстрока;Функция index возвращает позицию в строке, с которой начинается подстрока (имеется в виду первое вхождение подстроки, если их несколько). Если указана начальная позиция, то поиск начинается с этой позиции, иначе - с начала строки. Позиции в строке нумеруются, начиная с нуля. Если подстрока не найдена, функция возвращает -1.
# последовательный поиск всех вхождений $lookfor в строку $string $pos = -1; while (($pos=index($string, $lookfor, $pos)) > -1) { print "Found at position $pos\n"; $pos++; }
rindex
Функция rindex аналогична index, но возвращает позицию последнего вхождения подстроки в строку. В этом случае третий аргумент, если он указан, определяет позицию, на которой поиск следует прекратить.
Извлечение подстроки из строки в известной позиции
$подстрока = substr $строка, $смещение, $длина; $подстрока = substr $строка, $смещение;Функция substr извлекает из строки подстроку длиной длина, начинающуюся с позиции смещение. Если длина не указана, то подстрока извлекается от смещения до конца строки. Позиции в строке нумеруются, начиная с нуля.
Если смещение отрицательно, то оно отсчитывается не от начала, а от конца строки. Если длина отрицательна: длина=-N, то это значит, что извлекается подстрока такой длины, что она заканчивается за N символов до конца строки.
# все нижеследующие операции присваивают переменной $_ значение "abc" $_ = substr "xyzabcqqqq", 3, 3; $_ = substr "xyzabcqqqq", 3, -4; $_ = substr "xyzabcqqqq", -7, 3; $_ = substr "xyzabcqqqq", -7, -4;
Вставка/замена части строки в известной позиции
Для вставки подстроки в строку или замены одной подстроки другой подстрокой используется функция substr в левой части оператора присвоения. В этом случае первый аргумент функции substr обязан быть скалярным выражением, которому можно присвоить значение - скалярной переменной, элементом массива или элементом хэша. Примеры (перед каждым примером предполагается, что $a="abcdef"):
# 1) добавление подстроки "HELLO" в начало значения переменной $a substr($a,0,0) = "HELLO"; # в $a лежит "HELLOabcdef" # 2) замена второго и третьего символов в строке $_ словом "HELLO" substr($a, 1, 2) = "HELLO"; # в $a лежит "aHELLOdef" # 3) вставка слова "HELLO" между третьим и четвертым символами в строке $a substr($a, 3, 0) = "HELLO"; # в $a лежит "abcHELLOdef" # 4) замена последнего символа в строке $a словом "HELLO" substr($a, -1, 1) = "HELLO"; # в $a лежит "abcdeHELLO"
Вышеприведенные операции можно понимать так: из переменной $a извлекается указанная подстрока, а потом вместо нее в этой же позиции вставляется слово "HELLO".
Прочие функции
# удаляет один символ с конца строки $a; возвращает удаленный символ chop $a; # удаляет с конца строки символ перевода строки, если он там есть, # иначе строка остается без изменений; # возвращает количество удаленных символов chomp $a; #возвращает длину строки $a $l = length $a; #переводит все символы строки $a в верхний регистр uc $a; #переводит первый символ строки $a в верхний регистр ucfirst $a; #переводит все символы строки $a в нижний регистр lc $a;
Если аргументы вышеприведенных не указаны, подразумевается $_.
Функции описываются в любом месте скрипта с помощью конструкции
sub имя_функции { тело_функции; }и вызываются обычным образом:
имя_функции(аргумент1, аргумент2, ...); # со списком аргументов имя_функции(); # без аргументовСкобки при вызове написанных пользователем функций обязательны.
Количество и тип аргументов не декларируются и могут быть любыми и различными при последовательных вызовах одной и той же функции; все аргументы при передаче в функцию объединяются в единый список; внутри функции все аргументы доступны через массив @_ в том порядке, в каком они были указаны при вызове функции. Если аргументов не было, то массив @_ пуст. Хэш, переданный в качестве аргумента, преобразуется в список (о взаимоотношениях списков и хэшей см. выше п. "Типы переменных. Хэши").
sub function1 { # абсолютно бессмысленная функция - просто иллюстрация, как взять аргументы my $x = shift; # при этом первый аргумент удаляется из списка @_ # если @_ пуст, то $x=undef my ($y,$z) = @_; # а здесь аргументы из списка @_ не удаляются #(если они там вообще есть, иначе $y=$z=undef) print "Our first argument is ", defined $x ? $x : "empty", "\n"; $y ||=1; # а $y и $z присвоим значения по умолчанию $z ||=1; } sub function2 { # жутко полезная функция # предполагается, что в качестве аргументов поступают скаляр $k и хэш %h; # функция возвращает $h{$k} my $k = shift; # если $k пусто или в списке аргументов ничего не осталось - вернуть undef и выйти (defined $k and @_) or return undef; my %h=@_; return $h{$k}; } # вызов функции (например): $value=function2("my_key",%hash);
Каждая функция возвращает значение. Это может быть сделано явно с помощью оператора return, аргументом которого является скаляр или список. Если оператор return не встретился до конца функции, то возвращается значение последнего вычисленного выражения. Возвращаемое любой функцией значение может быть как использовано, так и проигнорировано вызывающей программой.
Каждая функция вызывается либо в скалярном, либо в списочном контексте; соответственным образом вызывающая программа интерпретирует возвращаемый функцией результат:
# ф-я f() возвращает список @array=f(); # списочный контекст - все тривиально $x=f(); # скалярный контекст - в $x помещается длина возвращаемого списка, а сам он пропадает # ф-я s() возвращает скаляр @array=s(); # списочный контекст - список @array теперь состоит из одного возвращенного значения $x=s(); # скалярный контекст - все тривиально
Для определения того, в каком контексте была вызвана функция, внутри нее используется оператор wantarray, возвращающий истину, если данная функция была вызвана в списочном контексте. Рассмотрим пример функции, которая возвращает список в списочном контексте и первый элемент списка - в скалярном.
sub f { # здесь как-то создается список @array # ... return wantarray ? @array : $array[0]; } push @biglist, f(); # списочный контекст, т.к. вторым аргументом функции push ожидается список $first=f(); # скалярный контекст
Внимание, распространенная ошибка! Если в функцию в качетсве аргументов переданы 2 массива: f(@ar1,@ar2), то внутри функции нет никаких способов определить, где в списке аргументов @_ кончается первый массив и начинается второй. Если внутри функции требуется различать эти массивы, то нужно передавать их в функцию в виде ссылок. Тоже самое касается и хэшей.
Закладки на сайте Проследить за страницей |
Created 1996-2024 by Maxim Chirkov Добавить, Поддержать, Вебмастеру |