Для сравнения скалярных данных или значений скалярных переменных язык Perl предлагает набор бинарных операций, вычисляющих отношения равенства, больше, больше или равно и т. п. между своими операндами, поэтому эту группу операций еще называют операциями отношения. Для сравнения числовых данных и строковых данных Perl использует разные операции. Все они представлены в табл. 4.1.

Таблица 4.1. Операции отношения

Операция Числовая Строковая Значение
Равенство == eq Истина, если операнды равны, иначе ложь
Неравенство != ne Истина, если операнды не равны, иначе ложь
Меньше < lt Истина, если левый операнд меньше правого, иначе ложь
Больше > gt Истина, если левый операнд больше правого, иначе ложь
Меньше или равно <= le Истина, если левый операнд больше правого или равен ему, иначе ложь
Больше или равно >= ge Истина, если правый операнд больше левого или равен ему, иначе ложь
Сравнение <=> cmt 0, если операнды равны
1, если левый операнд больше правого
-1, если правый операнд больше левого

Результатом операций отношения (кроме последней сравнения) является Истина, значение 1, или Ложь, пустая строка "".

Замечание
Значение истина в арифметических операциях интерпретируется как число 1, а в строковых как строка "1". Значение ложь в арифметических операциях интерпретируется как число 0, а в строковых как пустая строка " ".

Числовые операции отношения

Числовые операции отношения применяются к числовым данным, причем один или оба операнда могут задаваться строкой, содержащей правильное десятичное число. Если в числовых операциях отношения какой-либо из операндов задан строкой, содержимое которой не представляет правильное десятичное число, то его значение принимается равным о и отображается предупреждение о некорректном использовании операнда в числовой операции отношения (если включен режим отображения предупреждений интерпретатора Perl). Смысл операций отношения для числовых данных соответствует обычным математическим операциям сравнения чисел (пример 4.7).

123 > 89; # Результат: 1 (истина)

123 < 89; # Результат: "" (ложь)

123 <= 89; # Результат: "" (ложь)

89 <= 89; # Результат: 1 (истина)

23 >= 89; # Результат: "" (ложь)

23 <=> 89; # Результат: -1 (правый операнд больше левого)

89 <=> 23; # Результат: 1 (правый операнд больше левого)

Применение числовых операций сравнения не представляет сложности, однако при сравнении на равенство десятичных чисел с плавающей точкой могут проявиться эффекты округления, связанные с ограниченным количеством значащих цифр в мантиссе представления действительных чисел в компьютере и приводящие к "неправильной", с точки зрения пользователя работе операций сравнения. Пример 4.8 иллюстрирует подобную ситуацию.

#! peri -w
$z = 0.7;

$zz = 10+0.7-10; # Переменная $zz содержит число 0.7

# Печать строки "z равно zz", если равны значения переменных $z и $zz print "z равно zz\n" if ($z == $zz);

При попытке выполнить пример 4.8 мы с удивлением обнаружим, что наша программа ничего не напечатает. В чем же дело? Разгадка лежит в операторе вычисления значения переменной $zz. При выполнении арифметических операций в результате ошибок округления получается значение 0.699999999999999 (можете вставить оператор печати переменной $zz и убедиться в этом), хотя и близкое к 0.7, но не равное ему в точности. Следовательно, операция сравнения отработала верно!

Совет
Не используйте операцию сравнения на равенство вещественных чисел, ее результат может не соответствовать ожидаемому с точки зрения математики. Если необходимо проверить равенство двух вещественных чисел, то лучше сравнивать абсолютное значение их разности с некоторым очень маленьким числом (в зависимости от требуемой точности):

abs($a-$b) <= 0.00000001; # Проверка равенства

Строковые операции отношения

Сравнение строковых данных базируется на их упорядочении в соответствии с таблицей кодов ASCII, т. е. символ с меньшим кодом ASCII предшествует символу с большим кодом. Сравнение строк осуществляется посимвольно слева направо. Это означает, что если равны первые символы строк, то сравниваются вторые и если они равны, то сравниваются третьи и т. д. Причем, если строки разной длины, то в конец строки меньшей длины добавляется недостающее для равенства количество символов с кодом о. Следует отметить, что в отличие от некоторых других языков программирования в Perl замыкающие строку пробельные символы являются значимыми при сравнении строк. В примере 4.9 показаны сравнения строк, иллюстрирующие изложенные правила.

"A" It "a"; # Результат: истина (код "А" - \101, код "а" - \141)
"a" It "aa";
# с кодом \000, который меньше кода \141
# второго символа "а" строки правого операнда)
"a" It "a "; # Результат: истина (к строке "а" добавляется символ
# с кодом \000, который меньше кода \040
# замыкающего пробела строки правого операнда)
"12" It "9"; # Результат: истина (код "1" - \061, код "9" - \071)
"9" eq 09"; # Результат: ложь (код " " - \040, код "О" - \060)

Обратим внимание на две последние операции сравнения строковых литералов. Содержимое их операндов может быть преобразовано в правильные числа, и поэтому к ним применимы аналогичные числовые операции отношения. Однако их результат будет существенно отличаться от результата выполнения строковых операций отношения. При использовании операции < в предпоследнем выражении результат будет Ложь, а если в последнем выражении применить операцию ==, то результат будет Истина. Об этом всегда следует помнить, так как Perl автоматически преобразует символьные данные в числовые там, где это необходимо.

1.1 Введение

Perl - интерпретируемый язык, приспособленный для обработки произвольных текстовых файлов, извлечения из них необходимой информациии и выдачи сообщений. Perl также удобен для написания различных системных программ. Этот язык прост в использовании, эффективен, но про него трудно сказать, что он элегантен и компактен. Perl сочитает в себе лучшие черты C, shell, sed и awk, поэтому для тех, кто знаком с ними, изучение Perl-а не представляет особого труда. Cинтаксис выражений Perl-а близок к синтаксису C. В отличие от большинства утилит ОС UNIX Perl не ставит ограничений на объем обрабатываемых данных и если хватает ресурсов, то весь файл обрабатывается как одна строка. Рекурсия может быть произвольной глубины. Хотя Perl приспособлен для сканирования текстовых файлов, он может обрабатывать так же двоичные данные и создавать.dbm файлы, подобные ассоциативным массивам. Perl позволяет использовать регулярные выражения, создавать объекты, вставлять в программу на С или C++ куски кода на Perl-е, а также позволяет осуществлять доступ к базам данных, в том числе Oracle.
Ниже приводится в качестве примера небольшая программа, которая осуществляет доступ к Oracle.

#! /usr/local/bin/perl -w # запуск с ключом печати ошибок. use Oraperl; # подключение модуля для работы с Oracle $system_id = "T:bdhost.somwere.com:Base"; # описание имени базы данных $lda = &ora_login($system_id, "scott","tiger"); # подключение к базе данных пользователя # scott с паролем tiger $statement = "create table MYTABLE (NAME char(10), TITLE char(20), ORGANIZATION varchar2(256))"; # SQL команда создания таблицы MYTABLE $csr = &ora_open($lda, $statement) || die $ora_errstr; # открытие курсора csr, если это невозможно, # то осуществляется выход и печать сообщения об ошибке. &ora_close($csr); # закрытие курсора open(FL, "/home/my_home_directory/my_file") || die "Can"t open file \n"; # открытие файла, если это невозможно, # то выход с печатью сообщения об ошибке while ($string = ) { # чтение входного потока из файла с дескриптором FL @array = split(/\//,$string); # считанная строка разбивается в массив # строк, разделителем служит слеш $st = "insert into MYTABLE values(:1,:2,:3)"; # SQL команда помещения в таблицу некоторых значений $csr = &ora_open($lda,$st) || $ora_errstr; # открытие курсора или печать # сообщения об ошибке и выход &ora_bind($csr,$array,$array,$array); # привязка значений переменных к величинам, которые # требуется поместить в таблицу &ora_close($csr); # закрытие курсора } close FL; # закрытие файла &ora_commit($lda); # завершение транзакции в базе данных &ora_logoff($lda); # отключение от базы данных

2 Cтруктуры данных

Perl поддерживает три типа данных:

  • скаляры
  • массивы скаляров
  • ассоциативные массивы скаляров (так называемые хэши).

Обычные массивы, как и в языке C, индексируются числами, начиная с нуля. Ассоциативные массивы индексируются строками. Простые скаляры (в дальнейшем мы будем также называть их переменными) всегда начинаются со знака доллара: $, даже в том случае, когда мы обращаемся к элементу массива.

¯ $day простая переменная day $day 29 элемент массива day $day{"Feb"} значение "Feb" из хэша %day $#day последний индекс массива @day Простой массив начинается со знака @: ¯ @day массив day - ($day,$day,...) @day то же, что и @day Ассоциативный массив (хэш) начинается со знака процент %:
%day (key1, val1, key2, val2, ...)
Каждый тип данных имеет свое именное пространство, поэтому вы можете использовать одно и то же имя одновременно для скалярной переменной, массива или хэша (а также для подпрограммы или метки) без опасения, что произойдет ошибка. Perl различает большие и маленькие буквы: FOO, foo и Foo будут рассматриваться Perl-ом как разные переменные. Имена, начинающиеся с буквы или знака подчеркивания, могут в дальнейшем содержать в себе цифры или знаки подчеркивания. Имена, начинающиеся с цифры, могут в дальнейшем содержать только цифры. Имена, начинающиеся не с буквы, цифры или подчерка должны состоять только из одного символа. Большинство таких имен зарезервировано, например $$ является идентификатором текущего процесса. Интерпретация команды или величины часто зависит от требований контекста. Существует два основных контекста: скалярный и списковый. Некоторые операции возвращают список величин если в контексте подразумевается список и одну величину, если контекст скалярный. Например, операция &ora_fetch в скалярном контексте возвращает количество выбранных строк:
$nfields = &ora_fetch($csr);
В списковом контексте она возвращает массив выбранных строк:
@array = &ora_fetch($csr);
Левый аргумент определяет контекст правого аргумента.

2.1 Скалярные величины

Скалярные переменные могут содержать различные простые типы данных, такие как числа, строки или ссылки. Они не могут содержать сложные типы, но могут содержать ссылку на массив или хэш. В булевском контексте скаляр принимает значение TRUE, если он содержит не нулевое число или не пустую строку. В Perl существует несколько способов записи чисел:

¯ 12345 12345.67 .23E-10 0xffff шестнадцатеричная запись 0377 восьмеричная запись. 1_234_567_890 подчерк для удобства чтения. Строки заключаются в одинарные или двойные кавычки. Использование кавычек в Perl такое же как в bourne shell-е: строка в двойных кавычках обрабатывается и вместо переменных подставляются их значения, а также обрабатываются бакслэш-последовательности, строки в одинарных кавычках рассматривается просто как последовательности символов. Используются также: ¯ \t табуляция \n перевод строки \r возврат каретки \b пробел \e символ Escape \033 восьмеричный формат \x1b шестнадцатеричный формат \c[ управляющая последовательность (control) \a сигнал (alarm) \f переход на следующую страницу

2.2 Простые массивы

Perl позволяет произвольно удлинять массив путем обращения к элементу, индекс которого больше, чем последний индекс массива. Так же можно произвольно уменьшить длину массива.
@day = ("a","b");
$day = "c";
Теперь массив day содержит три элемента: ("a","b","c").
@day = (); или, что то же самое: $#day = -1;
Теперь массив day пуст.
(@day, @month, &SomeSub) содержит в себе элементы массива day, за ними следуют элементы массива month, а за ними результат выполнения подпрограммы SomeSub. Пустой массив обозначается (). Массив ((),(),(),()) эквивалентен пустому массиву. Последний элемент массива может быть массивом или хэшэм:
($a, $b, @c)= split;
($a, $b, %c)= @_;
Любой элемент массива может быть массивом.

2.3 Ассоциативные массивы

Ассоциативные массивы или хэши содержат пары ``ключ"" и ``значение"". Например:

\%map = ("red",0x00f,"blue",0x0f0,"green",0xf00); Часто для удобства чтения между ``ключом"" и ``значением"" ставят оператор =>. %map = ("red" => 0x00f, "blue" => 0x0f0, "green" =>)xf00);

3 Синтаксис языка Perl

3.1 Основные понятия

Программа на Perl-е состоит из последовательности команд. В отличие от типизированных языков Perl не требует объявления типов своих объектов. Все объекты, определенные в программе, до присваивания им какого-либо значения по умолчанию принимают значение ``0"". Последовательность команд исполняется сразу, в отличие от sed и awk, где исполняется последовательно каждая строка. Комментарии выделяются знаком #, и вся строка следующая за этим знаком будет рассматриваться как комментарий. Если вы написали подпрограмму, то ее можно вызывать только ниже по тексту программы. Блоком называется последовательность операторов, логически составляющая единое целое в теле программы, как правило, блоки заключаются в фигурные скобки. Каждая команда отделяется от других точкой с запятой. Точка с запятой не обязательна, только если оператор является последним в блоке.

3.2 Простые операторы

Последовательность простых операторов может следовать за отдельным модификатором. В Perl-е простыми модификаторами являются:
if (EXPR)
unless (EXPR)
while (EXPR)
until (EXPR) В операторах while и until проверка условия происходит перед выполнением тела блока, за исключением одного случая, когда используется do-оператор:

Do { $_ = ; ... } until $_ eq ".\n"; в котором проверка условия происходит после выполнения блока. Операторы цикла, которые будут описаны далее, не будут работать в этой конструкции, так как отсутствует метка цикла.

3.3 Составные операторы

if (EXPR) BLOCK
if (EXPR) BLOCK else BLOCK
if (EXPR) BLOCK eslif (EXPR) BLOCK else BLOCK
LABEL: while (EXPR) BLOCK
LABEL: while (EXPR) BLOCK continue BLOCK
LABEL: for (EXPR; EXPR; EXPR;...) BLOCK
LABEL: foreach VAR(LIST) BLOCK
LABEL: BLOCK continue BLOCK

В отличие от C и Pascal все определяется в терминах блоков, а не операторов: то есть фигурные скобки являются обязательными. Метка состоит из идентификатора и двоеточия. Она ставится в начале цикла и служит указателем для операторов цикла next, last и redo (их описание смотри ниже). Если это continue блок, то он выполняется перед тем, как условие будет проверено снова, как третья часть for оператора в C. Правильность условия может зависеть от результатов выполнения блока, например:

$i = 1; while ($i < 10){ ... } continue { $i++; } или, что тоже самое: for ($i = 1; $i < 10; $i++;) { ... } Foreach цикл присваивает переменной по очереди каждое значение из списка и выполняет над ней все команды из блока. Переменная является локальной и существует только в пределах данного цикла. Если список является массивом, то его можно изменять в цикле, посредством операций над переменной. Если переменная опускается, то по умолчанию в качестве нее используется $_. foreach \$elem(@elements) \{\$elem = \$elem * 2;\} -- цикл по всему содержимому массива @items. Пример: for ((1,2,3,4,5,6,7,8,9,10,"boom")) { print $_,"\n"; sleep(1); } for (1..15) { print "Merry Christmas\n"; } foreach $item (split(/[\/\*\\n]/,$ENV{"TERMCAP"})) { print "Item: $item\n"; } Блок семантически эквивалентен циклу, который исполняется один раз. Поэтому в него можно включать операторы контроля цикла, чтобы выйти из него или запустить его еще раз.

3.4 Операторы языка Perl

3.4.1 Термы и операторы списка

Операторы в Perl-е имеют различный приоритет. Операторы, заимствованные из C, сохранили между собой ту же иерархию, что и в C. Термы имеют самый большой приоритет, они содержат переменные, кавычки, выражения в скобках, функции с их параметрами. Если за списковым оператором (например, print()) или унарным оператором (например, chdir()) следует список аргументов, заключенный в скобки, то эта последовательность имеет самый высокий приоритет, подобно функции с аргументами. Аналогично термам обрабатываются последовательности do{} и eval{}.

3.4.2 Оператор ``стрелка""

Также, как в С и С++ ``->"" является инфиксным оператором ссылки. Если правая часть является [...] или {...} подпрограммой, тогда левая часть должна быть символьной ссылкой на массив или хэш. Если правая часть - это имя метода или скалярная переменная содержащая имя метода, то левая часть должна быть объектом или именем класса.

3.4.3 Операторы ++ и - -

Эти операторы работают также как и в С. То есть, если они стоят перед переменной, то они увеличивают или уменьшают переменную до возвращения значения. Если они стоят после переменной, то увеличение или уменьшение переменной происходит после возврата значения. Если переменная содержит в себе число или употребляется в скалярном контексте, то использование ++ дает обычное увеличение значения. Если же переменная употреблялась только в строковом контексте, не является пустой строкой и содержит символы a-z,A-Z,0..9, то происходит строковое увеличение значения переменной:
print ++($foo = "99"); - напечатает 100
print ++($foo = "a0"); - напечатает a1
print ++($foo = "Az"); - напечатает Ba
print ++($foo = "zz"); - напечатает aaa

3.4.4 Экспоненциальный оператор

В Perl-е двойная звездочка ** является экспоненциальным оператором. Он требует к себе даже больше внимания, чем унарный минус: -2**4 это -(2**4), но не (-2)**4.

3.4.5 Символьные унарные операторы

Унарный! означает логическое отрицание. Унарный минус, в случае числового значения переменной, обозначает обычное арифметическое отрицание. Если операндом является идентификатор, то возвращается строка, состоящая из знака минус и идентификатора. Если строка начинается со знака + или -, то возвращается строка, начинающаяся с противоположного знака. Унарная тильда ``~"" обозначает побитовое отрицание.
Унарный плюс не имеет влияния даже на строки. Он используется для отделения имя функции от выражения заключенного в скобки, которое иначе рассматривается как список аргументов.

Rand (10) * 20; - (rand10) * 20; rand +(10) * 20; - rand(10 * 20); Унарный бэкслэш ``"" обозначает ссылку на то, что стоит за ним.

3.4.6 Операторы связки

Знак равенства с тильдой ``=~""связывает выражение слева с определенным шаблоном. Некоторые операторы обрабатывают и модифицируют переменную $_. Эти же операции иногда желательно бывает выполнить над другой переменной. Правый аргумент это образец поиска, подстановки или трансляции, левый аргумент - это то, что должно быть подставлено вместо $_. Возвращаемая величина показывает успех операции. Бинарное ``!~"" это тоже самое, что и ``=~"", только возвращаемая величина является отрицательной в логическом смысле.

3.4.7 Бинарные операторы

Звездочка * - умножение двух чисел. Cлэш / - деление числа на число. Процент % - вычисляет модуль двух чисел, x - оператор повторения. В скалярном контексте возвращает строку, состоящую из многократно повторенного левого операнда, причем повторяется он то количество раз, которое стоит справа. В списковом контексте он многократно повторяет список. print "a" x 80; напечатает букву a 80 раз.
@ones = (1) x 80; массив из восьмидесяти единиц.
@ones = (5) x @ones сделает все элементы равными пяти.
Бинарный плюс - операция сложения двух чисел.
Бинарный минус - операция вычитания двух чисел.
Бинарная точка - конкатенация строк.

3.4.8 Операторы сдвига

Двоичный сдвиг осуществляется, как и во многих других языках программирования, с помощью операторов ``<<"" и ``>>"". При применении этих операторов значения левых аргументов сдвигаются в соответствующую сторону на количество разрядов, указанное в правых аргументах. Аргументы должны быть целочисленными.

3.4.9 Операторы сравнения

``<"" - возвращает TRUE если левый аргумент численно меньше, чем правый.
``>"" - возвращает TRUE если правый аргумент численно меньше, чем левый.
``<="" - возвращает TRUE если правый аргумент численно меньше или равен левому.
``>="" - возвращает TRUE если левый аргумент численно меньше или равен правому.
``gt"" - возвращает TRUE если левый аргумент меньше (в строковом контексте), чем правый.
``lt"" - возвращает TRUE если правый аргумент меньше (в строковом контексте), чем левый.
На поведение операторов lt и gt влияют установки системного языка, если операционная система способна работать с несколькими языками. По этой причине операторы должны корректно работать со строками на языках, отличных от US ASCII, что в системе UNIX задается указанием свойств LC_COLLATE системного locale.

3.4.10 Операторы эквивалентности

Возвращает TRUE, если левый аргумент численно эквивалентен правому.
!= возвращает TRUE, если левый аргумент численно неэквивалентен правому.
<=> возвращает -1, 0 или 1 в зависимости от того, численно меньше, равен или больше левый аргумент правого.
eq возвращает TRUE, если левый аргумент эквивалентен правому (в строковом контексте).
ne возвращает TRUE, если левый аргумент неэквивалентен правому (в строковом контексте).
cmp возвращает -1, 0 или 1 в зависимости от того, меньше равен или больше левый аргумент правого (в строковом контексте).

3.4.11 Побитовое И, побитовое ИЛИ и Исключающее ИЛИ

Бинарное & возвращает объединенные побитово операнды.
Бинарное | возвращает перемноженные побитово операнды.
Бинарное ^ возвращает исключенные побитово операнды.

3.4.12 Логическое И и логическое ИЛИ

Бинарное && - логическое И. Если левый аргумент FALSE, то правый не проверяется.
Бинарное || - логическое ИЛИ. Если левый аргумент TRUE, то правый аргумент не проверяется.
||""и && отличаются от подобных операторов в \verbC| тем, что вместо 0 или 1 они возвращают последнюю обработанную величину. Таким образом, наиболее удобным способом определить домашний каталог пользователя из переменной окружения HOME будет (на практике такой способ определения домашнего каталога пользователя не рекомендуется):

$home = $ENV{"HOME"} || $ENV{"LOGDIR"} || (getpwuid($<)) || die "You"re homeless!\n"; В качестве более удобной для чтения альтернативы Perl поддерживает операторы and и or, которые будут описаны далее. Их приоритет ниже, однако их можно с удобством использовать, не расставляя скобки, после операторов, аргументами которых являются списки: unlink "alpha", "beta", "gamma" or gripe(), next LINE; Если писать в стиле C, то это может быть записано так: unlink("alpha", "beta", "gamma") || (gripe(), next LINE);

3.4.13 Оператор диапазона

Оператор диапазона. Реально это два разных оператора, в зависимости от контекста. В списковом контексте он работает как оператор диапазона от левого аргумента до правого.

For (1..10) { #code } В скалярном контексте он возвращает булевское значение. Если левый операнд TRUE, то.. принимает значение TRUE, если правый операнд тоже TRUE. if (101..200) { print "hi;)";} - напечатает вторую сотню строк

3.4.14 Условный оператор

?: также как и в C является условным оператором. Он работает подобно if-then-else. Если аргумент перед? - TRUE, то возвращается аргумент перед:, в противоположном случае возвращается аргумент после:. Скалярный или списковый контекст второго и третьего аргументов передается по наследству.

($a_or_b ? $a: $b) = $c;

3.4.15 Операторы присваивания

Обычный оператор присваивания. Вообще операторы присваивания работают также как и в C. $a += 2; - то же самое, что и $a = $a + 2; Можно использовать следующие сокращения:

**= += *= &= <<= &&= -= /= |= >>= ||= .= %= ^= x= ($a += 2) *= 3; - то же самое, что и: $a = $a + 2; $a = $a * 3;

3.4.16 Оператор ``запятая""

Оператор запятая или comma-оператор. В скалярном контексте он обрабатывает левый аргумент и отбрасывает его значение, потом обрабатывает правый аргумент и возвращает его величину. В этом он подобен comma-оператору из C. В списковом контексте он играет роль разделителя аргументов и вставляет оба аргумента в список. => является синонимом comma-оператора.

3.4.17 Логическое НЕ

Унарное NOT возвращает отрицание аргумента. Оно эквивалентно!, за исключением более низкого приоритета.

3.4.18 Логическое И, ИЛИ и Исключающее ИЛИ

and возвращает конъюнкцию двух выражений. Он эквивалентен &&, за исключением более низкого приоритета. or возвращает дизъюнкцию аргументов. Он эквивалентен ||, за исключением более низкого приоритета. xor (eXclusive OR) - исключающее ИЛИ, возвращает истину, если истинен ровно один из аргументов.

3.4.19 Оператор чтения из файла

В Perl есть несколько операций ввода-вывода. Для вывода из файла используется команда <>.

Open(STDIN,"/etc/passwd"); while ($string = ) { @a = split(/[:]/,$string); } Внутри этих скобок стоит дескриптор файла. Считывание происходит построчно. В конце файла принимает значение FALSE и цикл while завершается. По умолчанию считывание происходит в переменную $_. Нулевой дескриптор файла используется также как в sed и awk, то есть считывается поток из файлов перечисленных в командной строке.

3.4.20 Оператор замены строки

Оператор s/PATTERN/REPLACEMENT/egimosx производит поиск строки, соответствующей шаблону PATTERN и если строка найдена, то подстановку на ее место текста REPLACEMENT. Возвращает количество произведенных подстановок. Если перед этим не использовался оператор =~ или!~ для определения переменной, которая будет обрабатываться, то будет модифицироваться переменная $_. Этот оператор используется со следующими опциями:

E интерпретирует правую часть как выражение. g производит подстановку на место каждой строки, соответствующей шаблону. i производит поиск различающий большие и маленькие буквы. m обрабатывает строку, как состоящую из нескольких строк. o происходит подстановка только на место первой встреченной строки. s обрабатывает строку, как состоящую только из одной строки. x использует расширенные регулярные выражения. Например: $path =~ s|/usr/local/bin|/usr/bin|; ($foo = $bar) =~ s/this/that/o; $count = ($paragraf =~ s/Mister\b/Mr./gm);

3.4.21 Оператор замены множества символов

tr/SEARCHLIST/REPLACEMENTLIST/cds y/SEARCHLIST/REPLACEMENTLIST/cds Заменяет все найденные символы из множества символов SEARCHLIST на соответствующие символы из множества символов REPLACEMENTLIST. Возвращает число символов, которые были заменены или удалены. Если посредством операторов =~, !~ не была указана никакая строка, то обрабатывается переменная $_. y является синонимом tr. Если SEARCHLIST заключен в скобки, то REPLACEMENTLIST тоже заключается в скобки, которые могут отличаться от тех, в которые заключается шаблон, например:

Tr tr(+-*/)/ABCD/ Этот оператор употребляется со следующими опциями: c заменяет символы, которые не входят во множество SEARCHLIST на REPLACEMENTLIST, например: tr/a-zA-Z/ /cs; заменит неалфавитные символы. d Стирает символы, которые ни на что не заменяются. s Переводит последовательность символов, которые заменяются на один и тот же символ в один символ. Например: $a = "CCCCCCCCC"; $a =~ tr/C/D/s; теперь $a = "D"

4 Языковые конструкции Perl

4.1 Ссылки

4.1.1 Основные понятия

В предыдущих версиях Perl была реализована возможность только символьных ссылок. Perl версии 5 и выше позволяет использовать не только символьные ссылки на переменные, но и ``жесткие"" ссылки на любые данные. Так как любой скаляр может быть ссылкой, а массивы и хэши состоят из скаляров, то можно с легкостью организовать массив массивов, массив хэшей, хэш массивов и так далее. ``Жесткие"" ссылки следят за счетчиком ссылки и как только счетчик становится равным нулю, автоматически удаляют ссылку. Символьные ссылки содержат только имя переменной, также как символьная ссылка файловой системы содержит просто имя файла. Ссылки могут быть созданы несколькими способами:

  1. Используя бэкслэш оператор перед переменной, подпрограммой или простой константой. (Это работает почти как & - создается еще одна ссылка, так как одна уже существует в символьной таблице.) $varref = \$foo; $arref = @ARGV; $hashref = \%ENV; $coderef = \&handler;
  2. Ссылка на массив может быть создана с использованием квадратных скобок: $arrayref = ]; По адресу $arrayref будет храниться значение b.
  3. Ссылка на произвольный хэш может быть создана с использованием фигурных скобок: $hashref = { "Earth" => "Moon", "Jupiter" => "Kallisto", ... };
  4. Ссылка на подпрограмму может быть создана с использованием слова sub, без определения имени подпрограммы: $coderef = sub { print "Hello!\n" };
  5. Ссылки часто возвращаются конструкторами. Объекты Perl на самом деле являются ссылками на специальную сущность, которая знает, какой пакет ассоциировать с объектом. Конструкторы это специальные подпрограммы, которые умеют создавать эту ассоциацию.
Чтобы извлечь информацию, на которую указывает ссылка, тоже существует несколько методов:
  1. Можно сделать идентификатор ссылки частью имени переменной или подпрограммы: $bar = $$scalarref; push(@$arrayref,$filename); $$arrayref = "January"; $$hashref{"key"} = "value"; &$coderef(1,2,3); $refrefref = \\\"how are you?"; print $$$$refrefref; - напечатает ``how are you?"".
    Нужно понимать, что раскрытие ссылки имеет более высокий приоритет, чем извлечение значения переменной.
  2. Можно поступить как и в предыдущем случае, но заключить выражение после знака $в фигурные скобки. Приведенный пример тогда будет выглядеть таким образом: $bar = ${$scalarref}; push(@{$arrayref},$filename); ${$arrayref} = "January"; ${$hashref}{"key"} = "value"; &{$coderef}(1,2,3); В данном случае использование фигурных скобок ничего не меняет, но в общем случае в скобках может стоять произвольное выражение, даже подпрограмма: &{ $dispatch{$index} }(1,2,3);
  3. В случае массива или хэша можно использовать такую запись: $arrayref-> = "January"; $hashref->{"key"} = "value"; Левая часть должна быть выражением, возвращающим ссылку, возможно также являющуимся раскрытием ссылки: $array[$x]->{"foo"}-> = "January";
  4. Если ссылка является ссылкой на объект, то раскрытие данных происходит также, как уже было описано выше.
Функция ref() может быть использована для определения типа объекта, на который указывает ссылка. Функция bless() может быть использована для ассоциирования ссылки с пакетом, функционирующим как объектный класс.

4.1.2 Символьные ссылки

Мы рассмотрели, что происходит, если величина, используемая в качестве ссылки, не была определена ранее. Что же происходит, если она уже определена и не является жесткой ссылкой? В таком случае она обрабатывается как символьная ссылка. То есть значение скаляра рассматривается как имя переменной, а не прямая ссылка на переменную.

¯ $name = "foo"; $$name = 1; - то же самое, что $foo = 1; ${$name} = 2; - то же самое, что $foo = 2; ${$name x 2 } = 3; -то же самое, что $foofoo = 3; $name-> = 4; -то же самое, что $foo = 4; @$name = (); - обнуляет массив @foo &$name(); - вызывает &foo

4.2 Регулярные выражения

Perl позволяет использовать регулярные выражения. Для того чтобы пояснить, что же представляет из себя регулярное выражение приведем несколько примеров:
/SWAP.*/ - соответствуют все слова начинающиеся со SWAP и заканчивающихся произвольным набором символов. Точка обозначает произвольный символ, звездочка - то, что символ, стоящий перед ней, входит в слово 0 и более раз. Все метасимволы, которые будут описаны ниже, бозначают вхождение того, что стоит перед ними.
/\w*/ - соответствуют слова состоящие только из алфавитных, цифровых символов и символа подчерк. \w - соответствует алфавитным, цифровым символам и символу подчерк, звездочка - тому, что эти символы могут входить произволное количество раз. Здесь мы приведем только основные метасимволы. Для более подробной информации смотрите соответствующие страницы man по Perl.

¯ * соответствует 0 или более вхождений + соответствует 1 или более вхождений? соответствует 1 или 0 вхождений {n} соответствует ровно n вхождений {n,} соответствует по крайней мере n вхождений {n,m} соответствует по крайней мере n, но не более m вхождений Метасимвол * эквивалентен {0,}, + эквивалентен {1,} и? эквивалентен {0,1}. Ограничений на величину m и n нет. Эта стандартная конструкция работает в ``жадном"" режиме, то есть: регулярному выражению a.*b будет соответствовать всевозможный набор слов начинающихся с символа a и кончающихся символом b, в том числе слова типа abcab. В таких словах есть подпоследовательности символов, которые также удовлетворяют условиям регулярного выражения. Если после каждого из описанных метасимволов поставить знак?, то подобные последовательности будут опускаться. Шаблоны обрабатываются как строка в двойных кавычках, поэтому приведенные ниже последовательности также будут обрабатываться: ¯ \l - передвижение на символ вниз \u - передвижение на символ вверх А также все перечисленные ранее бакслэш-последовательности. В Perl-е определены также: ¯ \w - соответствуют алфавитные и цифровые символы а также символ подчерк \$W - соответствуют все символы не входящие во множество символов w \s - символы пробела, табуляции, возврата каретки \S - все символы не входящие во множество символов s \d - цифровые символы \D - нецифровые символы Обратите внимание, что \w отмечает только отдельные символы, а не все слово. Чтобы отметить все слово нужно использовать \w+. Также определены следующие команды: ¯ \b - соответствуют границы слова \B - соответствуют не-границы слова \A - соответствуют только начало строки \Z - соответствуют только конец строки При использовании конструкции типа (...), \ подставляет подстроку из скобок с номером digit. Можно использовать скобки для отделения подшаблона. Если в скобках имеется более, чем 9 подстрок, то переменные $10, $11, ... содержат соответствующие подстроки. $+ возвращает то, чему соответствует последняя конструкция в скобках. $& возвращает подставленную строку. $` возвращает все перед подставленной строкой, $" возвращает все после подставленной строки. $_ = "abcdefghi"; /def/; print "$`:$&:$"\n"; - напечатает abc:def:ghi На этом мы закончим описание регулярных выражений, для более подробной информации читайте manual page.

4.3 Зарезервированные переменные

В Perl есть имена имеющие специальное значение. Многие из них аналогичны зарезервированным именам в shell.
Если вы хотите использовать длинные имена переменных, в заголовке программы требуется сказать:
use English;
Многие переменные доступны только для чтения, то есть при попытке присвоения такой переменной какого-либо значения напрямую или по ссылке происходит ошибка.

$_ В эту переменную по умолчанию происходит ввод, присваивание, в нее складываются результаты поиска по заданному образцу.

While(<>){...} или, что то же самое: while($_= <>) {...}

$ Эта переменная была описана в предыдущем параграфе. Она доступна только для чтения, так же как и переменные $&, $`, $" и $+.

$. Эта переменная содержит номер строки, которая была почитана последней из файла, который был прочитан последним. Она также доступна только для чтения.

$/ Содержит символ по которому разделяются вводимые записи. По умолчанию содержит символ перевода строки. Она похожа на переменную RS из awk.

$| По умолчанию имеет значение 0. Если содержит ненулевое значение, то происходит сброс буферов каждый раз после осуществления вывода (на печать, на экран и т.д.).

$, Содержит символ-разделитель полей для оператора печати. Подобна переменной OFS в awk.

$ Содержит символ-разделитель записей для оператора печати. Подобна переменной ORS в awk. (Вы можете определить $ вместо того, чтобы печатать n в конце печати.)

$" Подобна переменной $,. Но используется при обращении к списку величин в двойных кавычках (или другой строке, которая требует интерпретации). По умолчанию содержит символ пробел.

$; Содержит символ-разделитель для эмуляции многомерных хэшей. Если ссылаться на такой элемент хэша как $foo{$a,$b,$c} то реально это будет происходить так: $foo{join($;,$a,$b,$c)}. Не путайте с @foo{$a,$b,$c}, так как это тоже самое, что($foo{$a},$foo{$b},$foo{$c}). По умолчанию содержит значение \034 такое же как переменная SUBSEP в awk.

$# Формат для печати чисел. Подобна переменной OFMT в awk. Первоначально содержит значение %.20g.

$% Содержит номер текущей выводимой страницы.

$= Содержит длину текущей страницы (количество печатных срок), обычно содержит значение 60.

$- Содержит значение, определяющее количество оставшихся на странице строк, например количество еще не напечатанных строк для печатного канала вывода.

$~ Содержит имя текущего формата сообщений. Обычно имя дескриптора файла.

$^ Содержит имя текущего формата заголовка страницы. Обычно содержит имя дескриптора файла с добавлением в конце _TOP

$: Содержит множество символов после которых вывод сроки может быть прерван и начат снова после перевода строки.

$! Если эта переменная используется в числовом контексте, то содержит текущее значение errno (номер ошибки) со всеми обычными сообщениями. В строковом контексте содержит соответствующее системное сообщение об ошибке.

$@ Содержит сообщение о синтаксической ошибке, допущенной во время исполнения последней команды eval(). Если содержит значение 0, то команда была исполнена корректно. Но заметьте, что сообщения не накапливаются в этой переменной.

$$ Содержит идентификатор текущего процесса.

$< Содержит идентификатор пользователя (UID), которому принадлежит текущий процесс.

$> Содержит эффективный UID текущего процесса.

$( Содержит идентификатор группы (GID) пользователя, которому принадлежит текущий процесс.

$) Содержит эффективный GID текущего процесса.

$0 Содержит имя файла, в котором находится исполняемая программа.

$ARGV Содержит имя текущего файла, из которого происходит чтение.

@ARGV Содержит массив аргументов командной строки, которые были переданы программе.

@INC Содержит список точек входа в программу, в которых используются конструкции do EXPR, require и use.

%INC Содержит входы для каждого файла, который включается посредством использования операторов do или require. Ключами являются имена файлов, а значениями места их расположения.

%ENV Содержит текущее окружение процесса. Изменением содержимого хэша можно изменить окружение порожденного (дочернего) процесса.

%SIG Этот хэш используется для установки обработчиков различных сигналов. Например:

Sub handler { local($sig) = @_; print "Caught a SIG$sig - shutting down\n"; close(LOG); exit(0); } $SIG{"INT"} = "handler"; $SIG{"QUIT"} = "handler"; ... $SIG{"INT"} = "DEFAULT"; $SIG{"QUIT"} = "IGNORE";

4.4 Встроенные функции

abs VALUE Возвращает абсолютное значение аргумента.

accept NEWSOCKET, GENERICSOCKET подобно системному вызову accept(2) ждет соединения. Возвращает запакованный адрес, если соединение произошло успешно и FALSE в противоположном случае.

atan2 Y,X Возвращает arctg(Y/X).

bind SOCKET, NAME Привязывает сетевой адрес к сокету, также как системный вызов bind в OS UNIX или любой другой системе, поддерживающей BSD Sockets. Если привязка произошла успешно, возвращает TRUE, в противном случае - FALSE. Переменная NAME должна содержать запакованный адрес, соответствующего для сокета типа. Тип адреса для разных видов сокетов определяется в терминах языка C структурой sockaddr, которая представляет собой абстрактный тип, содержащий все данные, необходимые для сокета.

bless REF, PACKAGE Эта функция присоединяет объект на который указывает ссылка REF, к пакету PACKAGE, если он определен, если же он опущен, то к текущему пакету. Для удобства возвращает ссылку, так как bless() часто является последним оператором в конструкторе.

caller EXPR Возвращает контекст текущего вызова подпрограммы. В скалярном контексте возвращает TRUE, если мы находимся внутри подпрограммы, eval() или require(). FALSE в противоположном случае. В списковом контексте возвращает:

($package, $filename, $line) = caller; С аргументом EXPR возвращает более сложную информацию, которая используется отладчиком для печати карты стека. Значение EXPR отмечает глубину стека до текущей записи. ($package, $filename, $line, $subroutine, $hasargs, $wantargs) = caller($i);

chdir EXPR Изменяет текущую директорию на указанную в EXPR, если это возможно. Если EXPR опущено, то устанавливает в качестве текущей директории домашнюю директорию. Возвращает TRUE в случае успеха и FALSE иначе.

chmod LIST Изменяет права доступа к файлам указанным в LIST. Первым аргументом должна быть маска доступа в цифровом формате. Возвращает число файлов права доступа к которым были успешно сменены.

$cnt = chmod 0700 "foo","bar"; chmod 700 @executables;

chown LIST Изменяет хозяина или группу, которой принадлежит список файлов. Первыми двумя аргументами должны быть uid и gid. Возвращает количество успешных изменений.

chr NUMBER Возвращает символ, представленный номером NUMBER в наборе символов. Например, chr(65) вернет A.

close FILEHANDLE Закрывает файл с дескриптором FILEHANDLE. Для более подробной информации читайте manual page.

Open(OUTPUT "/usr/home/petrov"); ... close OUTPUT;

closedir DIRHANDLE Закрывает каталог открытый вызовом opendir().

connect SOCKET,NAME Пытается соединиться с удаленным сокетом (по аналогии с системным вызовом). Возвращает TRUE в случае успешного соединения и FALSE в противоположном случае. Переменная NAME должна содержать запакованный адрес соответствующего данному сокету типа.

cos EXPR Возвращает косинус EXPR, выраженного в радианах. Если EXPR опущено, возвращает косинус $_.

dbmopen ASSOC, DBNAME, MODE Связывает dbm(3) или ndbm(3) файл с ассоциативным массивом. ASSOC - имя ассоциативного массива. DBNAME - имя базы данных (без.dir или.pag расширения). Если база данных не существует, то она создается с правами доступа указанными в MODE.

Dbmopen(%HIST,"/usr/lib/news/history", 0600); while (($key, $val) = each %HIST){ print $key, "=", unpack("L",$val),\n;} dbmclose(%HIST);

dbmclose ASSOC Прерывает связь между файлом и ассоциативным массивом.

defined EXPR Возвращает TRUE или FALSE, в зависимости от того определено значение EXPR или нет. Многие операции возвращают неопределенное значение в случае конца файла, неинициализированной переменной, системной ошибки или при подобной ситуации. Если речь идет о хэше, то defined покажет только определены ли ли величины, ничего не говоря о существовании ключей. Для определения существования ключей используется функция exists().

delete EXPR Стирает указанную величину. Возвращает удаленную величину или значение не определено в случае, если удаление не произошло.

Foreach $key (keys %array) { delete $array{$key}; } Но более быстро то же самое можно сделать используя функцию undef().

die LIST Вне eval() печатает значение LIST в STDERR и выходит из программы с текущим значением $!. Если значение $! есть ноль, то принимает значение $? >> 8. Если значение $? >> 8 есть ноль, то принимает значение 255. Внутри eval() сообщение об ошибке помещается в переменную $@ и eval() прерывается с неопределенным значением.

Open(FL, "/root/rm-rf") || die "Can"t open file.\n";

do BLOCK Функцией не является. Возвращает значение последней операции внутри блока.

do EXPR Использует величину EXPR как имя файла и далее запускает содержимое этого файла, как программу на Perl. Обычно это используется для включения библиотечных подпрограмм.

Do "stat.pl"; Это то же самое, что: eval "cat stat.pl"; Однако подключать библиотечные модули более удобно используя use и require.

each ASSOC_ARRAY Возвращает массив из двух элементов, содержащий ключ и значение из хэша, причем по очереди перебирает все пары ($key, $value).

While (($key,$value) = each %ENV){ print " $key = $value \n"; }

eof FILEHANDLE Возвращает 1, если следующее считывание возвращает конец файла или если FILEHANDLE не был открыт. При опущении аргумента eof обрабатывает последний файл, из которого происходило считывание. Но на практике эта функция редко используется, так как в Perl-е операторы чтения возвращают неопределенное значение в конце файла.

eval EXPR EXPR выполняется как маленькая программа в контексте основной программы. Определенные переменные и подпрограммы остаются определенными и в дальнейшем. Возвращается значение, которое возникает при обработке последнего выражения. Если EXPR опущено, то обрабатывается $_.

exec LIST Исполняет внешнюю программу и НИКОГДА не возвращает управление. На самом деле (в UNIX) производится системный вызов семейства exec, который подменяет программу, исполняющуюся в рамках текущего процесса. Если LIST представляет собой список из более, чем одного аргумента, то вызывается execvp(3) с аргументами из LIST. Если аргумент только один, то он проверяется на метасимволы shell. Если они присутствуют, то он далее передается /bin/sh -c для обработки. Если же их нет, то аргумент передается напрямую execvp, который более эффективен.

exists EXPR Возвращает TRUE, если в хэше есть ключи и даже в том случае, когда значения VALUE не определены.

exit EXPR Обрабатывает EXPR и осуществляет немедленный выход с полученной величиной.

$ans = ; exit 0 if $ans =~ /^/; Если EXPR опущено, то осуществляет выход с нулевым статусом.

exp EXPR Возвращает е (основание натурального логарифма e = 2.718281828...) в степени EXPR. По умолчанию обрабатывается $_.

fork Делает системный вызов fork(2). Возвращает pid (идентификатор процесса) дочернего процесса родительскому процессу и 0 дочернему процессу. Значение не определено в случае неуспешного завершения команды. Неуспех может произойти, например, в случае установки в системе ограничения на количество процессов данного пользователя. Вот небольшой пример использования этой функции.

Unless ($pid = fork) { unless (fork) { exec "what you really wanna do"; die "no exec"; some_perl_code_here; exit 0; } exit 0; } waitpid($pid,0);

getc FILEHANDLE Возвращает следующий символ из файла чтения, присоединенный к FILEHANDLE или пустую строку в случае конца файла. Если FILEHANDLE опущен, то считывание происходит из STDIN.

goto LABEL Эта функция осуществляет переход на точку программы LABEL и продолжает выполнение программы с этой точки. Точка не может находиться внутри подпрограммы или foreach цикла, так как в этих случаях требуется предварительная инициализация. Использовать в качестве LABEL выражение не рекомендуется, хотя такая возможность и предоставляется.

grep BLOCK, LIST

grep EXPR, LIST Обрабатывает BLOCK или EXPR для каждого элемента LIST и возвращает список элементов для которых значение выражения TRUE. В скалярном контексте возвращает число элементов для которых EXPR TRUE.

hex EXPR Возвращает десятичное значение EXPR, интерпретируемого как шестнадцатеричная строка. По умолчанию обрабатывает переменную $_.

kill LIST Посылает сигнал списку процессов LIST, первым элементом списка должен быть номер сигнала. Возвращает число процессов, которым сигнал был послан успешно. В отличие от shell, если номер сигнала отрицателен, то он посылается группе процессов.

int EXPR Возвращает целую часть EXPR, если EXPR опущено, то обрабатывает переменную $_.

join EXPR,LIST Соединяет в единую строку строки из LIST. При этом в качестве разделителей между элементами LIST ставит значение EXPR. Например:

$_ = join(":",$login,$passwd, $uid,$gid,$gcos,$home,$shell);

keys ASSOC_ARRAY Возвращает обычный массив, состоящий из ключей ассоциативного массива ASSOC_ARRAY. В скалярном контексте возвращает число ключей.

@keys = keys %ENV;

length EXPR Возвращает длину EXPR в символах. По умолчанию обрабатывает переменную $_.

link OLDFILE,NEWFILE Создает файл NEWFILE, присоединенный к файлу OLDFILE. (В OS UNIX создание нескольких имен для одного файла) Возвращает 1 в случае успеха и 0 иначе.

listen SOCKET, QUEUESIZE Делает то же самое, что и одноименный системный вызов. Возвращает TRUE в случае успеха, FALSE иначе.

local EXPR На самом деле гораздо эффективнее использовать функцию my. Функция local делает перечисленные переменные локальными в блоке, подпрограмме, eval или do. Если переменных более, чем одна, то они должны объединяться скобками.

Sub RANGEVAL{ local($min,$max,$thunk) = @_; local $result = ""; local $i; for ($i = $min; $i < $max; $i++) { $result = eval $thunk; } $result; }

log EXPR Возвращает натуральный логарифм EXPR, по умолчанию обрабатывает переменную $_.

map EXPR,LIST Подставляет каждый элемент из списка LIST в EXPR (которое может быть блоком) и возвращает список полученных после обработки величин.

@chars = map(chr, @nums);

mkdir FILENAME,MODE Создает директорию с именем FILENAME и правами доступа указанными в переменной MODE. В случае успеха возвращает 1, в противном случае возвращает 0 и устанавливает значение переменной $!(errno).

my EXPR Эта функция (так же как и описанная ранее функция local) делает перечисленные переменные локальными в пределах блока, подпрограммы, eval или do. Если список состоит более чем из одного элемента, то он должен быть заключен в скобки. Все элементы в списке должны быть фактическими параметрами. В отличие от local, переменные локализованные функцией my не видны снаружи блока, подпрограммы или другой конструкции, внутри которой my употребляется.

next LABEL Употребляется подобно continue оператору в C - запускает следующую итерацию цикла.

Line: while () { next line if /^#/; ... }

oct EXPR Возвращает десятичное значение EXPR, интерпретируемого как строка в восьмеричном формате. (Если строка начинается с 0x, то интерпретируется, как строка в шестнадцатеричном формате.)

open FILEHANDLE,EXPR Открывает файл, имя которого описано в переменной EXPR и привязывает его к FILEHANDLE. Если EXPR опущено, то переменная с таким же именем как FILEHANDLE содержит имя файла. Если имя файла начинается со знака:

¯ < файл открывается на чтение. > файл открывается на запись. >> файл открывается для добавления. | имя файла расценивается как команда, с которой будет организован программный канал, то есть вывод в дескриптор FILEHANDLE будет передаваться на вход программе EXPR.

Если знак | указывается после имени команды, то вывод этой команды будет ассоциирован с дескриптором FILEHANDLE, из которого будет производиться чтение. Интересно, что нельзя открыть двойной программный канал, то есть ассоциировать ввод и вывод команды с дескриптором файла (что соответствовало бы системному вызову popen в UNIX).

В случае, когда имя файла оканчивается вертикальной чертой, оно расценивается как имя команды, вывод которой будет интерпретироваться как ввод из файла (аналог функции popen(3)).

Open(LOG, ">>/usr/spool/news/twitlog");

open DIRHANDLE,EXPR Открывает директорию с именем EXPR, возвращает TRUE в случае успеха.

ord EXPR Возвращает числовое значение в таблице ASCII первого символа EXPR. По умолчанию обрабатывает переменную $_.

print FILEHANDLE,LIST Печатает строку или несколько строк, разделенных запятой. FILEHANDLE может быть именем скалярной переменной, содержащей дескриптор файла. Если эта переменная опущена то печать идет в выбранный канал вывода. Если переменная LIST тоже опущена, то печатает переменную $_ в STDOUT.

printf FILEHANDLE, LIST Эквивалентно print FILEHANDLE, sprintf(LIST). Первый аргумент LIST интерпретируется как формат печати.

rand EXPR Возвращает выбранное случайным способом значение между 0 и EXPR. EXPR должно быть положительным. По умолчанию производит выборку в диапазоне между 0 и 1. (Замечание: если ваша функция постоянно возвращает слишком большие или слишком малые значения, то скорее всего была допущена ошибка при компиляции вашей версии Perl. Было установлено неверное значение RANDBITS.)

read FILEHANDLE,SCALAR,LENGTH,OFFSET Считывает LENGTH байт данных из FILEHANDLE в переменную SCALAR. Возвращает число считанных байт или неопределенное значение в случае ошибки. Если вы хотите считать данные не с начала строки, то для этого нужно установить значение переменной OFFSET.

readlink EXPR Возвращает значение символьной ссылки, если она существует. Если же ее нет, то выдает fatal error и устанавливает значение переменной $!. По умолчанию обрабатывает переменную $_.

redo LABEL Перезапускает цикл без повторной обработки условия. Блок continue, если он есть не исполняется. Если LABEL опущена, то команда выполняется для внутреннего цикла.

Line: while() { while ($_ ne "\") { if (ord $_ < 86) { ... } redo line; } print; }

ref EXPR Возвращает TRUE, если EXPR является ссылкой и FALSE в противоположном случае. Полученное значение зависит от типа объекта на который указывает ссылка. Существует несколько встроенных типов данных:

  • SCALAR
  • ARRAY
Если объект, на который указывает ссылка, находится в пакете (package), то в таком случае возвращается имя пакета. if (ref($r) eq "HASH") { print " Это ссылка на ассоциативный массив.\n"; } if (!ref($r)) { print " А это не ссылка вовсе! \n";

require EXPR Используется для подключения модулей.

Require "oraperl.pm";

reset EXPR Обычно используется в continue блоке в конце цикла для переустановки значений переменных. EXPR интерпретируется как список отдельных символов. Значения переменных и массивов, имена которых начинаются с одного из этих символов списка переустанавливаются. Например:

¯ reset "X" переустановит все X переменные reset "a-z" переустановит все переменные, имена которых состоят из маленьких букв.

rm FILENAME Удаляет файл или директорию с заданным именем. Возвращает 1 в случае успеха, 0 в противоположном случае и устанавливает значение переменной $!. По умолчанию обрабатывает аргумент $_.

scalar EXPR Выражение будет трактоваться в скалярном контексте. Возвращает значение EXPR.

seek FILEHANDLE, POSITION, WHENCE Позволяет установить курсор в файле, определенном в переменной FILEHANDLE, на позицию POSITION в режиме, указанном в переменной WHENCE. Если переменная WHENCE содержит значение 0, то позиция отсчитывается от начала файла, если 1 то от текущей позиции и если 2, то от конца файла. Возвращает 1 в случае успеха и 0 иначе.

select FILEHANDLE Возвращает текущий выбранный FILEHANDLE. Направляет вывод в FILEHANDLE.

select RBITS,WBITS,EBITS,TIMEOUT Вызывает системный вызов select(2) с определенной аргументами битовой маской.

shift ARRAY Сдвигает массив ARRAY влево с удалением первого элемента и возвращает удаленный элемент. Если в массиве нет элементов, то возвращает неопределенное значение. Если ARRAY опущен, то обрабатывает массив @ARGV в главной программе и массив @_ в подпрограммах.

sin EXPR Возвращает синус выражения EXPR (выраженного в радианах). Если аргумент опущен, то обрабатывается переменная $_.

sleep EXPR Дает процессу команду остановки на EXPR секунд. Если аргумент опущен, то процесс зависает навсегда. В таком случае ``сон"" можно прервать, послав ему сигнал. Возвращает число секунд, в течение которых процесс был в состоянии остановки.

socket SOCKET,DOMAIN,TYPE,PROTOCOL Создает сокет и привязывает его к дескриптору файла SOCKET. Остальные параметры описываются так же, как и в одноименном системном вызове. В начале программы необходимо написать use Socket;.

sort SUBROUTINE,LIST Сортирует аргументы из LIST и возвращает отсортированный список. Если список является массивом, то несуществующие элементы массива не учитываются и не возвращаются. Ниже приведено несколько примеров.

@articles = sort @files; - Лексическая сортировка без использования подпрограммы. @articles = sort{$a cmp $b} @files; - То же самое, но с использованием подпрограммы. @articles = sort{$a <=> $b} @files; - Численная сортировка по возрастанию.

splice ARRAY,OFFSET,LENGTH,LIST Удаляет из массива ARRAY элементы, отмеченные в переменных OFFSET и LENGTH и заменяет их элементами списка LIST, если таковые имеются. Возвращает удаленные из массива элементы. Длина массива растет или уменьшается, если это необходимо. Если переменная LENGTH опущена, то удаляет все, начиная с OFFSET.

split /PATTERN/,EXPR,LIMIT Разбивает строку на массив строк и возвращает его. В скалярном контексте возвращает число полученных полей и помещает полученный массив в @_. Если EXPR опущено то разбивается строка $_. Если PATTERN тоже опущен, то разбиение происходит по символу пробел. Символы, указанные в PATTERN, служат разделителями для полей. Разделители могут быть длиннее, чем один символ. Если переменная LIMIT задана и имеет неотрицательное значение, то разбиение будет происходить на число полей не более указанного в LIMIT. Если переменная не определена, то пустые поля отбрасываются, если имеет отрицательное значение, то это интерпретируется Perl-ом, как отсутствие ограничения на длину возвращаемого массива. Если шаблону соответствует пустая строка, то EXPR будет разбито на отдельные символы. Например:

Print join(":",split(/ */,"hi there")); напечатает строку h:i:t:h:e:r:e.

sqrt EXPR Возвращает корень квадратный из значения EXPR. По умолчанию обрабатывает переменную $_.

system LIST Делает то же самое, что и функция exec LIST, за одним исключением: вместо того, чтобы просто начать выполнять программу, как это делает exec, system делает fork и порождает еще один процесс, причем родительский процесс ждет завершения дочернего.

tell FULEHANDLE Возвращает текущую позицию курсора в файле FILEHANDLE. Если аргумент опущен, то обрабатывает файл, который читался последним.

tie VARIABLE,PACKAGENAME,LIST Привязывает переменную к пакету, который будет заносить значения в эту переменную. Переменная VARIABLE содержит имя переменной, переменная PACKAGENAME содержит имя пакета. Дополнительные аргументы передаются методу new этого пакета. Обычно это такие аргументы, которые в дальнейшем могут быть переданы в качестве параметров dbm_open() функции из C.

Tie(%HIST, NDBM_File,"/usr/lib/news/history", 1, 0); while(($key,$val) = each %HIST) { print $key, "= ", unpack("L",$val),"\n"; } untie(%HIST); Пакет, реализующий ассоциативный массив, должен содержать следующие методы:
TIEHASH objectname, LIST
DESTROY this
FETCH this, key
STORE this, key, value
DELETE this, key
EXISTS this, key
FIRSTKEY this
NEXTKEY this, lastkey
Пакет, реализующий обычный массив, должен содержать следующие методы:
TIEARRAY objectname, LIST
DESTROY this
FETCH this, key
STORE this, key, value
Пакет, реализующий скаляры, должен содержать следующие методы:
TIESCALAR objectname, LIST
DESTROY this
FETCH this
STORE this, value

truncate FILEHANDLE, LENGTH Обрезает файл FILEHANDLE до заданной длины.

undef EXPR Делает значение EXPR неопределенной величиной, в случае, когда аргумент опущен ничего не меняет. Не следует пытаться применять эту функцию к зарезервированным переменным, потому что результат может оказаться непредсказуемым.

unlink LIST Удаляет список файлов и возвращает число удачно удаленных файлов. Если вы не являетесь суперпользователем, то эта функция не может удалять каталоги. Даже в случае, когда программа запускается с привилегиями суперпользователя, будьте осторожны, лучше использовать функцию rmdir.

untie VARIABLE Разрывает связь между переменной и пакетом.

unshift ARRAY, LIST Производит действие противоположное действию функции shift. Присоединяет LIST к началу массива ARRAY и возвращает новое количество элементов в массиве.

use Module LIST Осуществляет присоединение модуля к программе.

Use strict qw(subs,vars,refs);

values ASSOC_ARRAY Возвращает обычный массив, состоящий из значений ассоциативного массива ASSOC_ARRAY. В скалярном контексте возвращает число элементов полученного массива. Элементы массива могут располагаться в произвольном порядке.

wantarray Возвращает TRUE, если контекст исполняющейся подпрограммы списковый, FALSE в противоположном случае.

write создает запись (возможно состоящую из нескольких строк) в соответствующем файле, используя формат ассоциированный с этим файлом. Формат для текущего канала вывода может быть установлен посредством присваивания переменной $~{ } имени формата.

4.5 Подпрограммы и модули

4.5.1 Подпрограммы

Описать и использовать подпрограмму можно несколькими способами:

  1. sub NAME; - подразумевает описание в дальнейшем тела подпрограммы.
  2. sub NAME BLOCK - непосредственное описание.
  3. $subref = sub BLOCK - анонимное описание.
  4. use PACKAGE qw(NAME1, NAME2, NAME3) - включение подпрограмм из модулей.
Вызвать подпрограмму можно тоже несколькими способами:
  1. &NAME(LIST) - скобки обязательны для & формы.
  2. NAME(LIST) - & не обязательно со скобками.
  3. NAME LIST - скобки можно опустить в случае предварительного описания или включения подпрограммы из модуля.
Аргументы передаются подпрограмме в виде локального массива @_, его элементы являются ссылками на реальные скалярные параметры. Подпрограмма возвращает значение, полученное в результате исполнения последнего оператора подпрограммы. Как уже говорилось, подпрограмма вызывается использованием префикса & перед ее именем, в Perl 5 этот префикс не обязателен. Пример: sub MAX { my $max = pop(@_); foreach $foo (@_) { $max = $foo if $max < $foo; } $max; } ... $bestmark = &MAX(1,2,3,4,5); Подпрограмма может вызываться рекурсивно. Если подпрограмма вызывается с использованием & формы, то список аргументов необязателен. Если вы хотите создать внутри модуля его собственную, невидимую снаружи подпрограмму, то описание должно быть анонимным: my $subref = sub {...} &$subref(1,2,3);

4.5.2 Пакеты

Perl поддерживает механизм альтернативного именного пространства для каждого отдельного пакета. Обычная программа является пакетом с именем main. Можно ссылаться на переменные или дескрипторы файлов из других пакетов посредством использования префикса перед именем переменной, состоящего из имени пакета и двойного двоеточия: $Package::Variable. Если имя пакета нулевое, то предполагается использование переменной из main пакета. То есть $::sail эквивалентно $main::sail. Пакеты могут включать в себя другие пакеты, в таком случае чтобы обратиться к переменной нужно применить описанное обозначение рекурсивно: $OUTER::INNER::var.
В пакете могут содержаться только переменные, чьи имена начинаются с буквы или подчерка, остальные переменные содержатся в пакете main. Кроме того зарезервированные переменные, как то STDIN, STDOUT, STDERR, ARGV, ARGVOUT, ENV, INC и SIG также содержатся в главном пакете.

Package mypack; sub main::mysub { ... }

4.5.3 Таблицы символов

Таблицы символов пакета хранятся в ассоциативном массиве с тем же именем и двойным двоеточием в конце. Для пакетов включенных в пакет имя символьной таблицы составляется аналогичным образом: %OUTER::INNER::.

4.5.4 Конструкторы и деструкторы пакетов

Существует две функции специального вида - конструкторы и деструкторы. Это BEGIN и END программы в их описании необязательно использование sub. Подпрограмма BEGIN исполняется сразу, как только это возможно, то есть в момент, когда она полностью определена, даже перед тем как обрабатывается остаток содержащего файла. В файле может быть несколько блоков BEGIN. Они исполняются в порядке определения.
Подпрограмма END исполняется в самом конце. В файле может содержаться несколько END блоков, они исполняются в обратном порядке.

4.5.5 Классы

В Perl 5 нет специального синтаксиса для описания классов, но пакеты могут функционировать как классы, если они содержат подпрограммы функционирующие как методы. Такие пакеты могут также брать некоторые методы из других пакетов-классов. Для этого необходимо перечислить имена других пакетов в массиве @ISA.

4.5.6 Модули

В Perl 5 понятие пакетов расширено в понятие модулей. Модули это пакеты находящиеся в одноименном файле, включенном в библиотеку. Модули подключаются следующим образом:

Use Module; или use Module LIST; Это эквивалентно: BEGIN { require "Module.pm"; import Module; } Все модули имеют расширение.pm. Если именное пространство модуля пересекается с именным пространством основной программы то всегда используется use, если не пересекается то можно использовать require.
Стандартные модули Perl описаны в документации.

5 Объектная ориентация

Понятие объектной ориентации зиждется на трех простых определениях:

  1. Объект это просто ссылка.
  2. Класс это просто пакет, который содержит методы для работы с объектными ссылками.
  3. Метод это просто подпрограмма, которая имеет своим первым аргументом объектную ссылку (или имя пакета для статического метода).

5.1 Объекты

В отличие от C++, Perl не имеет специального синтаксиса для описания конструкторов. Конструктор, как уже говорилось раньше, это просто подпрограмма, которая возвращает ссылку ассоциированную с классом (как правило с тем, где определена подпрограмма). Например, типичный конструктор:

Package Critter; sub new { bless {} } {} создает ссылку на анонимный хэш.
В пределах класса методы как правило работают с обычными ссылками. Конструктор может привязать объект к другому классу, в таком случае предыдущая привязка бывает забыта, так как объект не может принадлежать одновременно нескольким классам.

5.2 Классы

В отличие от C++, Perl не имеет специального синтаксиса для описания классов. Классом является пакет, чьи подпрограммы выступают в качестве методов. Для каждого пакета определен специальный массив @ISA, в котором перечислены пакеты, подключенные к данному пакету. Таким образом в Perl реализован механизм наследования методов. Метод, принадлежащий другому объекту, подключается как подпрограмма.

5.3 Методы

В Perl-е метод имеет синтаксис простой подпрограммы. В качестве первого аргумента метода выступает объект или пакет. Существует два типа методов: статические и виртуальные методы.
Статические методы имеют первым аргументом имя класса. Они обеспечивают функциональность для класса в целом, а не для отдельных объектов принадлежащих классу. Конструкторы являются, как правило, статическими методами. Многие статические методы просто игнорируют свой первый аргумент, так как заранее знают, какому пакету они принадлежат. Другой способ использования статических методов состоит в том, что метод работает с объектом, используя имя:

Sub find { my ($class, $name) = @_; $objtable{$name}; } Виртуальные методы имеют первым аргументом ссылку на объект. Обычно они помещают эту ссылку в переменную self или this и в дальнейшем используют ее как обычную ссылку. sub display { my $self = shift; my @keys = @_ ? @_ : sort keys %$self; foreach $key (@keys) { print "\t$key => $self ->{$key}\n"; } }

5.4 Вызов метода

Существует два способа обратиться к методу. Во-первых, можно вызвать его просто как подпрограмму. Но в таком случае не работает механизм наследования. Второй способ лучше просто проиллюстрировать примерами.

$fred = find Critter "Fred"; display $fred, "Height", "Weight"; Это можно записать так: display {find Critter "Fred"} "Height", "Weight";

5.5 Деструкторы

Когда удаляется последняя ссылка на объект, этот объект автоматически удаляется. Это может произойти даже после завершения программы, если ссылки на объект содержались в глобальных переменных. Если необходимо контролировать процесс удаления объекта, можно определить в объекте специальный метод, называемый деструктором . Деструктор объекта (в отличие от C++) имеет фиксированное имя DESTROY и вызывается перед удалением объекта. В нем можно реализовать дополнительные процедуры, необходимые для корректного завершения (например, удаление временных файлов, используемых объектом).

Логические операторы

Л огические операторы анализируют булевы выражения и возвращают значения или в качестве результата. Perlобрабатывает операнды логических операций как булевы величины, т.е. как истинное или ложное значение.

Л огические операторы языка Perl включают следующие:


    || логическое ИЛИ

    && логическое И

P erl всегда обрабатывает логические выражения слева направо. Кроме того. Perl всегда прекращает оценку, если уже выполненнойоценки достаточно, чтобы определить значение результата.

В дополнение к общим логическим операторам Perl поддерживает следующие дополнительные логические операторы:


    Логическое отрицание

    ?: - условная операция

    Последовательное выполнение

О ператор логического отрицания (!) заменяет значение булевой величины на противоположную. Так же как и в С, в языке Perl условный оператор (?:) использует три операнда. Выражение, использующее условный оператор, имеет следующую форму:

Condition ? true-result: false-result

А налогично, следующее выражение использует условный оператор длятого, чтобы предоставить Бобу полный доступ, а всем остальным ограниченный:

$access = ($user eq "Bob" ? "Full" : "Limited");

О ператор последовательного выполнения (также известный какоператор запятая) не является вполне логическим оператором, поскольку он не анализирует истинность своих операндов. Perl выполняет операнды оператора последовательного выполнения слева направо и возвращает значение самого правого операнда.

С ледующий пример иллюстрирует использование оператора запятая в цикле for.

For ($i=0, $j=10; $i {
print i$," ",$j
}

Строковые операторы

П оскольку Perl представляет собой язык для обработки текста, неудивительно, что в него включены дополнительные операторы для работы со строками. Ниже перечисляются операторы обработки строк:


    Конкатенация строк

    х репликация

    =~ сопоставление переменной с образцом

    !~ то же, что и предыдущее, но с дополненным отрицанием результата

П ервые два оператора легко иллюстрируются примером:

Print "b" . "an" x 2 . "a"; # выведет "banana"

К ак показано, это выражение использует конкатенацию строк иоператор репликации для того, чтобы напечатать строку . Два последних оператора используются для проверки того, включаетли строковый операнд заданный образец. Этот вопрос детально обсуждается в разделе Регулярные выражения .

С ледующий пример иллюстрирует их использование:

$var = "banana";
print ($var =~ /ana/) ? TRUE: FALSE;

В этом случае оператор проверки вхождения в строку образца(=~) использовался для проверки того, входит ли образец ana в переменную $var. В данном случае выражение принимает значение.

Операторы присваивания

Е сли вы знакомы с языком программирования С, то формы операторов присваивания языка Perl должны быть для вас совершенно знакомыми. Так же как и в С, эти операторы заставляют Perl выполнить специальные операции со значениями, которые появились с правой стороны оператора, и затем выполнить присваивание:

= += -= *= /= %= |= &=
^= ~= >>= **= .= x=

L VALUES В языке Perl, так же как и в С, lvalue представляет собой имя того, что стоит с левой стороны оператора присваивания. Таким образом, lvalue представляет собой целостность, которой может быть присвоено значение, например, lvalue может быть переменной. Например, скрипт Perl не может присвоить значение строке символов, наподобие выражения = 32, поскольку не является lvalue. Тем не менее, скрипт может присвоить значение переменной $Bob, например, следующим образом $Bob = 32, поскольку переменная $Bob является lvalue. В языке Perl любая целостность, которая может использоваться как lvalue, обычно таковой и является. Например, следующее выражение упаковывает (pack) и распаковывает (unpack) список значений, причем список переменных в первом случае и три скалярных во втором являются lvalues:

@color = ($r, $g, $b); # пакет цветов
($r, $g, $b) = @color; # распаковка цвета

К огда вы работаете со списками в языке Perl, оператор присваивания не обяза тельно относится ко всему списку. Скрипт можетприсваивать значения отдельным элементам списка, как показано ниже:

@items = (100,200,300);

В этом случае оператор присваивает значение трем элементамсписка. Аналогичным образом следующее выражение распаковываетэлементы списка, присваивая значения двух первых элементов двумскалярным переменным, а остаток массива - списочной переменной:

($arg1,$arg2,@rest) = @ARGV; # можно смешать скаляры и массивы

6.5.1. Простые операторы

Простой оператор в PERLе — это выражение, которое может иметь единственный модификатор. Каждый простой оператор должен закачиваться точкой с запятой, если только он не является последним оператором в блоке; в этом случае точка с запятой может быть опущена. Существует пять модификаторов простых операторов:

$count = 5; print "$count\n" if $count; print "$count\n" while $count--; @people = qw/Анна Борис Виктор/; print "$_\n" foreach @people;

Мы можем применять модификаторы не только к простым операторам, но и к блокам. Для этого перед блоком нужно поставить ключевое слово do :

Do { $line = ; ... } until $line eq ".\n";

Такой блок всегда исполняется хотя бы раз до проверки условия. Обратите внимание, что в таких конструкциях не работают операторы управления циклом, поскольку модификаторы не имеют меток.

Конструкция do БЛОК (без модификатора) также используется в PERLе: она позволяет превратить блок в выражение и возвращает значение последнего оператора в этом блоке.

6.5.2. Составные операторы

Составные операторы состоят из блоков , заключенных в фигурные скобки. Напомним, что, в отличие от языков C или Java, фигурные скобки в составных операторах обязательны, даже если в них заключен только один оператор. PERL содержит следующие составные операторы:

6.5.2.1. Условный оператор if

Условный оператор if позволяет проверить определенное условие и, в зависимости от его истинности, выполнить ту или иную последовательность операторов. Он имеет следующие формы:

if (выражение ) БЛОК1 if (выражение ) БЛОК1 else БЛОК2 if (выражение1 ) БЛОК1 elsif (выражение2 ) БЛОК2 ... else БЛОКn

выражение истинно, то выполняется БЛОК1 ; если оно ложно, то управление передается оператору, следующему за if .

выражение истинно, то выполняется БЛОК1 ; если оно ложно, то выполняется БЛОК2 .

Третья форма оператора означает, что если выражение истинно, то выполняется БЛОК1 ; если оно ложно и истинно выражение2 , то выполняется БЛОК2 и т. д. Если ложны выражения во всех ветках оператора, то выполняется БЛОКn .

Следующий пример присваивает переменной $m наибольшее из трех чисел $x , $y , $z:

If ($x >= $y) { $m = ($x >= $z) ? $x: $z; } else { $m = ($y >= $z) ? $y: $z; }

6.5.2.2. Условный оператор unless

Условный оператор unless if . Он имеет две формы:

unless (выражение ) БЛОК1 unless (выражение ) БЛОК1 else БЛОК2

Первая форма оператора означает, что если выражение ложно, то выполняется БЛОК1 ; если оно истинно, то управление передается оператору, следующему за unless .

Вторая форма оператора означает, что если выражение ложно, то выполняется БЛОК1 ; если оно истинно, то выполняется БЛОК2 .

Предыдущий пример можно переписать так:

Unless ($x < $y) { $m = ($x >= $z) ? $x: $z; } else { $m = ($y >= $z) ? $y: $z; }

6.5.2.3. Оператор цикла while

Оператор цикла while имеет две формы:

while (выражение ) БЛОК while (выражение ) БЛОК continue БЛОК1

Оператор while

  1. Вычисляется значение выражения
  2. Выполняется БЛОК .
  3. continue , то выполняется БЛОК1 .

$i = 0; while ($i++ < 10) { print "$i\n" }

Пользуясь второй формой оператора while , его можно записать так:

$i = 1; while ($i <= 10) { print "$i\n" } continue { $i++ }

При использовании данного оператора необходимо убедиться, что рано или поздно выражение станет ложным, т. к. иначе программа войдет в бесконечный цикл, например:

While (1) { print "Привет всем!" }

6.5.2.4. Оператор цикла until

Оператор цикла until логически противоположен оператору while и также имеет две формы:

until (выражение ) БЛОК until (выражение ) БЛОК continue БЛОК1

Оператор until выполняется следующим образом:

  1. Вычисляется значение выражения . Если оно истинно, то управление передается оператору, следующему за данным оператором.
  2. Выполняется БЛОК .
  3. Если оператор содержит ключевое слово continue , то выполняется БЛОК1 .
  4. Управление передается этапу 1.

Следующий пример выводит на экран числа от одного до десяти:

$i = 1; until ($i > 10) { print "$i\n" } continue { $i++ }

6.5.2.5. Оператор цикла for

Оператор цикла for имеет вид:

for (инициализация ; условие ; изменение ) БЛОК

Оператор for выполняется следующим образом:

  1. Выполняется оператор инициализация (обычно он инициализирует счетчик или счетчики цикла).
  2. Вычисляется значение выражения условие . Если оно ложно, то управление передается оператору, следующему за данным оператором.
  3. Выполняется БЛОК .
  4. Выполняется оператор изменение (обычно он увеличивает или уменьшает счетчик или счетчики цикла) и управление передается этапу 2.

Данный оператор обычно используется в тех случаях, когда количество повторений цикла известно заранее. Так, мы могли бы записать предыдущий пример короче:

For ($i = 1; $i <= 10; $i++) { print "$i\n" }

6.5.2.6. Оператор итерации foreach

Оператор foreach выполняет заданные действия для каждого элемента списка или массива. Он имеет две формы:

foreach переменная (список ) БЛОК foreach переменная (список ) БЛОК continue БЛОК1

Оператор foreach выполняется следующим образом:

  1. Переменной присваивается очередной элемента списка . Если список исчерпан, то управление передается оператору, следующему за данным.
  2. Выполняется БЛОК .
  3. Если оператор содержит ключевое слово continue , то выполняется БЛОК1 .
  4. Управление передается этапу 1.

Приведем все тот же пример с печатью чисел от 1 до 10:

Foreach $i (1..10) { print "$i\n" }

Переменная является локальной для данного оператора, т. е. после завершения итерации ее предыдущее значение восстанавливается. Если перед переменной поставить ключевое слово my , то она будет лексически ограничена телом оператора. Если переменная опущена, то используется специальная переменная $_ :

Foreach (1..10) { print "$_\n" }

Если одним из элементов списка является массив, то тело цикла не должно его изменять, иначе результаты непредсказуемы.

В действительности, операторы for и foreach являются синонимами, и вы можете использовать любое из этих слов по своему усмотрению.

6.5.2.7. Метки операторов

Перед операторами while , until , for и foreach , а также перед блоками могут ставиться метки . Помеченный оператор имеет вид:

метка : оператор

В качестве метки может использоваться любой идентификатор, который не является зарезервированным словом, но на PERLе принято писать метки заглавными буквами.

Хотя в современном программировании использование меток считается дурным тоном, в некоторых случаях их применение существенно упрощает логику программы. Чаще всего это происходит, когда метки используются для передачи управления из глубоко вложенного цикла к внешнему. Рассмотрим следующий пример, написанный в лучший традициях C++:

For (my $i = 0; $i < @ary1; $i++) { for (my $j = 0; $j < @ary2; $j++) { if ($ary1[$i] > $ary2[$j]) { last; } $ary1[$i] += $ary2[$j]; } }

Метки и операторы управления циклом позволяют записать этот алгоритм намного короче и, главное, намного прозрачнее:

OUTER: for my $x (@ary1) { for my $y (@ary2) { next OUTER if $x > $y; $x += $y; } }

6.5.2.8. Оператор last

Оператор last немедленно завершает указанный цикл. Он имеет две формы:

last метка last

Первая форма оператора завершает выполнение цикла с заданной меткой . Вторая форма завершает выполнение самого внутреннего из выполняющихся в данный момент вложенных циклов. Если цикл имеет блок continue , то он не выполняется. Пример:

LINE: while () { last LINE if /^$/; # прервать цикл, если встретилась пустая строка... }

6.5.2.9. Оператор next

Оператор next начинает новую итерацию указанного цикла. Он имеет две формы:

next метка next

меткой continue , то он будет выполнен перед началом новой итерации. Пример:

LINE: while () { next LINE if /^#/; # пропускать комментарии... }

6.5.2.10. Оператор redo

Оператор redo начинает новую итерацию указанного цикла без проверки условия его выполнения. Он имеет две формы:

redo метка redo

Первая форма оператора начинает новую итерацию цикла с заданной меткой . Вторая форма начинает новую итерацию самого внутреннего из выполняющихся в данный момент вложенных циклов. Если цикл имеет блок continue , то он не выполняется. Следующий пример удаляет комментарии из программы на языке Pascal, где они имеют вид {…} (пример упрощен, т. к. не учитывает, что символы {} могут содержаться в строковых константах):

LINE: while () { while (s|({.*}.*){.*}|$1 |) {} s|{.*}| |; if (s|{.*| |) { $front = $_; while () { if (/}/) { s|^|$front\{|; redo LINE; } } } print; }

6.5.2.11. Блок как вырожденный цикл

Блок рассматривается в PERLе как цикл, безусловно выполняющийся один раз. Это означает, что мы можем использовать конструкцию

БЛОК1 continue БЛОК2

которая обычно означает, что выполняется БЛОК1 , а после него БЛОК2 . Однако, трактовка блоков как циклов означает и то, что мы можем пользоваться внутри блоков операторами управления циклом, и в этом случае указанная конструкция становится очень полезной.

Одна из причин, по которым в PERL не включен оператор выбора switch , состоит в том, что очень легко моделируется с помощью блоков и операторов управления циклом, например:

SWITCH: { $abc = 1, last SWITCH if /^abc/; $def = 1, last SWITCH if /^def/; $xyz = 1, last SWITCH if /^xyz/; $nothing = 1; }

6.5.2.12. Оператор перехода goto

PERL содержит оператор перехода goto трех видов:

goto метка goto выражение goto &имя

Первая форма оператора передает управление оператору с указанной меткой . Управление не может быть передано внутрь конструкции, требующей инициализации, например, внутрь подпрограммы или оператора foreach .

Вторая форма — это "вычисляемый goto ": он вычисляет значение выражения и передает управление на полученную в результате метку, например:

Goto ("LABEL1", "LABEL2", "LABEL3")[$i];

Третья форма — это вообще не goto в обычном смысле слова. Этот оператор подставляет вызов подпрограммы имя вместо выполняющейся сейчас подпрограммы. Она используется подпрограммами AUTOLOAD(), которые хотят незаметно подменить вызов одной подпрограммы другой. Имя не обязано быть именем подпрограммы; это может быть скалярная переменная или блок, значением которых является ссылка на подпрограмму.

Рассмотрены интересные неочевидные конструкции Perl.

Как известно, язык программирования Perl очень выразителен и имеет в своем арсенале множество средств, которые позволяют выразить намерения программиста в коде множеством совершенно разных образов. Также, в виду весьма хитрого синтаксиса, некоторые комбинации операторов могут приводить к интересным эффектам.

Также, некоторые вещи можно использовать не совсем стандартным образом для получения желаемого результата. Такие действия иногда называются «забивать гвозди микроскопом». Именно этим мы и будем заниматься.

  • Поведение операторов, приведенных в этой статье, может меняться от версии к версии Perl.
  • Данные операторы, скорее всего, не предназначены для использования их в production.
  • Большинство этих операторов были созданы людьми, которым приносит удовольствие исследовать любимый язык.
  • Все, что приведено ниже и названо операторами, на самом деле ими не является.

Оператор «Венера»

0+ +0

Название

Свое название оператор получил от внешней схожести с символом Венеры.

Что делает?

Приводит аргумент слева, или справа, в зависимости от версии, к числовому виду. Например:

Print 0+ "23a"; print 0+ "3.00"; print 0+ "1.2e3"; print 0+ "42 EUR"; print 0+ "two cents";

Результат:

23 3 1200 42 0

Этот оператор с натяжкой можно использовать у себя в проектах, но не следует забывать о том, что с точки зрения Perl числами, например, являются: 0 but true 0E0 и некоторые еще хитрые константы. Еще следует отметить, что 0+ это метод, используемый для числового преобразования по умолчанию при использовании overload .

«Черепашка», «Детская коляска» или «Тележка из супермаркета»

@{}

Название

Свое название оператор получил из-за внешней схожести с черепахой или коляской. Примечателен тем, что был открыт Ларри Уоллом в 1994 году.

Что делает?

Это так называемый контейнерный оператор, который позволяет производить интерполяцию массива внутри строки. Элементы массива в результате будут разделены содержимым переменной $" .

Как работает?

Сначала содержимое принудительно вычисляется в списковом контексте, затем, незамедлительно, проводится разыменование (@{ }).

Print "Test i am @{[ die()]}"; print "here";

Результат работы:

Died at demo.pl line 1.

Этот оператор можно использовать для выполнения произвольного кода в строках, когда происходит интерполяция. Например, с его помощью можно сделать некоторые вещи проще, например, построение SQL-запросов:

My $sql = "SELECT id, name, salary FROM employee WHERE id IN (@{[ keys %employee ]}) SQL ";

но выигрыш в пару строк кода не оправдывает потенциальные проблемы в безопасности (хорошая практика в SQL - использование т.н. bind variables, которые будут подставлены при prepare). В виду неочевидности, использовать оператор в production не стоит, потенциальная уязвимость и уменьшение читабельности.

Bang Bang

!!

Данный оператор использовался еще тогда, когда Perl не было, его часто использовали программисты на С.

Как работает?

Этот оператор делает следующую элементарную вещь - двойное отрицание, суть которого сводится к булевому преобразованию. Вспоминаем, что булевых типов в Perl нет.

My $true = !! "a string"; my $false = !! undef;

В результате $true содержит 1 , а $false пустую строку "" . Данный оператор можно использовать для проверки, есть ли значение, например, в ссылке на хеш, например

!! $hash->{value} or die("Missing value");

Червяк

~~

Название?

Просто и незатейливо похож на гусеницу-пяденицу, и на многих червей также.

Как работает?

Оператор ~~ внешне очень похож на smart matching, но им не является потому, что это унарный оператор.

Унарная операция - это операция над одним операндом

Тогда как smart matching - операция бинарная (операция над двумя операндами, сложение, например).

Что делает?

Всего-лишь сокращенное на четыре (!) символа ключевое слово scalar .

Perl -Esay~~localtime Tue Jul 30 17:43:16 2013

Принцип действия оператора схож с оператором Bang Bang (!!), но отличается тем, что в Perl оператор ~ операторозависимый. Более подробно можно узнать, посмотрев в документации про побитовые операции в Perl. Применять этот оператор можно, но следует быть осторожным, неизвестно, как он будет себя вести на всех версиях perl.

Червяк-на-палочке

-~ ~-

Это высокоприоритетный оператор инкремента/декремента. -~ инкрементирует только числа, которые меньше нуля, а ~- декрементирует числа больше нуля

Приоритет этого оператора выше арифметических операторов, кроме возведения в степень (**). Например:

$y = ~-$x * 4;

Будет исполняться идентично:

$y = ($x-1)*4;

Но не как:

$y = ($x * 4) -1

Для того, чтобы данные операторы работали с беззнаковыми типами данных, необходимо использовать прагму integer (use integer). Этот оператор работает весьма неплохо и его можно применять в production, но делать этого не стоит, т.к. на нестандартных архитектурах его поведение может отличаться от вышеуказанного. Хотелось бы попробовать его в действии на ARM-платформах, но автор статьи не располагает подобным устройством.

Космическая станция

-+-

Открыт Alistair McGlinchy в 2005 году.

Этот оператор производит высокоприоритетное приведение к числовому виду, по поведению он похож на оператор «символ Венеры», но он отличается следующими вещами. Оператор Венеры (0+ или +0) использует бинарный оператор + , тогда как «Космическая станция» использует сконкатенированные три унарных оператора, а потому имеет более высокий приоритет.

Также, стоит помнить, что этот оператор имеет меньший приоритет, чем сконкатенированные операторы * и x . Принципы его работы можно проиллюстрировать следующим примером, в котором мы попробуем распечатать приведенное к числовому виду "20GBP" три раза:

Неправильно, т.к. возвращает преобразованный вариант от строки "20GBP20GBP20GBP" :

Print 0+ "20GBP" x 3; # 20

Неправильно, т.к. эквивалентно (print "20") x 3:

Print(0+ "20GBP") x 3; # 20

Правильно, но сильно длинно, сильно «лиспово»:

Print((0 + "20GBP") x 3); # 202020

Правильно - используя оператор «Космическая станция»:

Print -+- "20GBP" x 3; # 202020

Однако, т.к. унарный минус - и унарный + просто заменяет результат строки на его значение, то данный оператор не будет работать со следующего вида строками:

  • С теми, что начинаются на - .
  • С теми, что начинаются на не числовой символ.

Тогда как оператор Венеры работает во всех этих случаях, но имеет меньший приоритет.

Goatse или Сатурн-оператор

=()=

Что делает?

Этот оператор вводит списковый контекст справа от него и возвращает количество элементов слева.

Как работает?

Список в скалярном контексте возвращает количество элементов. Не имеет значения, сколько элементов из них было присвоено переменным. В таком случае правая часть выражения будет приведена к пустому списку, а затем, следовательно, отброшена.

$n =()= /word1|word2|word3/g; $n =()= "abababab" =~ /a/; # $n = 1 $n =()= "abababab" =~ /a/g; # $n = 4

К тому же, данный оператор является контейнерным (!), что позволяет запросто «втянуть» в него результат правой части. Это значит, что мы можем поступать следующим образом:

$n =($b)= "abababab" =~ /a/g; # $n = 4; $b = "a" $n =(@c)= "abababab" =~ /a/g; # $n = 4; @c = qw(a a a a)

Следующий «хитрый» пример его использования, похоже, имеет право на жизнь, но существует другой секретный оператор, который может делать то же самое.

Допустим, мы хотим узнать, на сколько частей разобьет строку split, а сами элементы нас не интересуют, может быть, есть смысл попробовать нечто следующего вида:

My $count = split /:/, $string;

Этот пример вернет нам необходимое число, но при этом ругнется на:

Use of implicit split to @_ is deprecated

Для того, чтобы решить данную проблему мы можем воспользоваться данным оператором и написать нечто подобное:

My $count =()= split /:/, $string;

Что не вызовет warning, но при этом будет всегда возвращать 1 потому, что split никогда не разбивает строку на большее количество частей, чем необходимо. В свою очередь, компилятор расценивает попытку сохранить в () как утверждение в том, что данные элементы нам не надо и вернет неизмененную строку, что будет приведено к списку с одним элементом.

Есть два возможных решения.

Первое заключается в том, что мы можем запретить компилятору проводить оптимизацию split() , указав при помощи -1 желание получить бесконечное количество кусков строки:

My $count =()= split /:/, $string, -1;

Или использовать другой секретный оператор, «черепашку»:

My $count = @{[ split /:/, $string ]};

Воздушный змей

~~<>

На самом деле, данный оператор является всего-лишь комбинацией Червяка и <> . Он предоставляет скалярный контекст для операции readline() , но полезный он только в контексте списка.

Богато украшенный двусторонний меч

<> m ;

Этот секретный оператор предоставляет мультистрочные комментарии и не более того. Пример использования:

<> Use the secret operator on the previous line. Put your comments here. Lots and lots of comments. You can even use blank lines. Finish with a single m ;

Но следует учитывать тот факт, что данный комментарий - просто строка, заключенная в двойные кавычки, а потому может иметь некоторые побочные эффекты.

Отверточные операторы

Обнаруженный Дмитрием Карасиком в процессе поиска операторов, базирующихся на! . Как и отвертки, эти операторы бывают четырех основных типов, но с разной длиной рукоятки:

Прямая отвертка - обеспечивает декремент по условию:

$x -=!! $y # $x-- if $y; $x -=! $y # $x-- unless $y;

Крестовая отвертка - инкремент по условию:

$x +=!! $y; # $x++ if $y; $x +=! $y; # $x++ unless $y;

Отвертка-звездочка - сброс переменной в 0 по условию:

$x *=!! $y; # $x = 0 unless $y; $x *=! $y; # $x = 0 if $y;

Крестообразная отвертка-шлиц - сброс переменной в ’’ по условию:

$x x=!! $y; # $x = "" unless $y; $x x=! $y; # $x = "" if $y;

Enterprise-оператор

()x!!

Довольно часто возникает необходимость добавить элемент в список по условию. Это можно сделать следующим образом:

My @shopping_list = ("bread", "milk"); push @shopping_list, "apples" if $cupboard{apples} < 2; push @shopping_list, "bananas" if $cupboard{bananas} < 2; push @shopping_list, "cherries" if $cupboard{cherries} < 20; push @shopping_list, "tonic" if $cupboard{gin};



Эта статья также доступна на следующих языках: Тайский

  • Next

    Огромное Вам СПАСИБО за очень полезную информацию в статье. Очень понятно все изложено. Чувствуется, что проделана большая работа по анализу работы магазина eBay

    • Спасибо вам и другим постоянным читателям моего блога. Без вас у меня не было бы достаточной мотивации, чтобы посвящать много времени ведению этого сайта. У меня мозги так устроены: люблю копнуть вглубь, систематизировать разрозненные данные, пробовать то, что раньше до меня никто не делал, либо не смотрел под таким углом зрения. Жаль, что только нашим соотечественникам из-за кризиса в России отнюдь не до шоппинга на eBay. Покупают на Алиэкспрессе из Китая, так как там в разы дешевле товары (часто в ущерб качеству). Но онлайн-аукционы eBay, Amazon, ETSY легко дадут китайцам фору по ассортименту брендовых вещей, винтажных вещей, ручной работы и разных этнических товаров.

      • Next

        В ваших статьях ценно именно ваше личное отношение и анализ темы. Вы этот блог не бросайте, я сюда часто заглядываю. Нас таких много должно быть. Мне на эл. почту пришло недавно предложение о том, что научат торговать на Амазоне и eBay. И я вспомнила про ваши подробные статьи об этих торг. площ. Перечитала все заново и сделала вывод, что курсы- это лохотрон. Сама на eBay еще ничего не покупала. Я не из России , а из Казахстана (г. Алматы). Но нам тоже лишних трат пока не надо. Желаю вам удачи и берегите себя в азиатских краях.

  • Еще приятно, что попытки eBay по руссификации интерфейса для пользователей из России и стран СНГ, начали приносить плоды. Ведь подавляющая часть граждан стран бывшего СССР не сильна познаниями иностранных языков. Английский язык знают не более 5% населения. Среди молодежи — побольше. Поэтому хотя бы интерфейс на русском языке — это большая помощь для онлайн-шоппинга на этой торговой площадке. Ебей не пошел по пути китайского собрата Алиэкспресс, где совершается машинный (очень корявый и непонятный, местами вызывающий смех) перевод описания товаров. Надеюсь, что на более продвинутом этапе развития искусственного интеллекта станет реальностью качественный машинный перевод с любого языка на любой за считанные доли секунды. Пока имеем вот что (профиль одного из продавцов на ебей с русским интерфейсом, но англоязычным описанием):
    https://uploads.disquscdn.com/images/7a52c9a89108b922159a4fad35de0ab0bee0c8804b9731f56d8a1dc659655d60.png