Войти
Немного о компьютере
  • История операционной системы BlackBerry
  • «Темы из сторонних источников не поддерживаются» в MIUI: как обойти запрет Xiaomi темы
  • Samsung Galaxy Ace Plus - Технические характеристики Samsung Galaxy Ace Plus GT-S7500: отзывы
  • Как прошить htc desire x, и где скачать прошивку?
  • Создание виртуального образа диска в домашних условиях
  • Обзор Sharp AQUOS S2 – безрамочный, необычный, классный Новый sharp
  • Perl условия. Основы Perl — условные операторы и циклы. Богато украшенный двусторонний меч

    Perl условия. Основы Perl — условные операторы и циклы. Богато украшенный двусторонний меч

    В дополнение к всеобъемлющему списку операторов сравнения строк Sinan Ünür Perl 5.10 добавляет оператор интеллектуального соответствия.

    Оператор smart match сравнивает два элемента в зависимости от их типа. См. Диаграмму ниже для поведения 5.10 (я считаю, что это поведение немного меняется в 5.10.1):

    perldoc perlsyn "Умное соответствие в деталях" :

    Поведение умного соответствия зависит от того, что это за аргументы. Он всегда коммутативен, т.е. $a ~~ $b ведет себя так же, как $b ~~ $a . Поведение определяется следующей таблицей: первая строка, которая применяется в любом порядке, определяет поведение совпадения.

    $a $b Type of Match Implied Matching Code ====== ===== ===================== ============= (overloading trumps everything) Code[+] Code[+] referential equality $a == $b Any Code[+] scalar sub truth $b−>($a) Hash Hash hash keys identical ~~ Hash Array hash slice existence grep {exists $a−>{$_}} @$b Hash Regex hash key grep grep /$b/, keys %$a Hash Any hash entry existence exists $a−>{$b} Array Array arrays are identical[*] Array Regex array grep grep /$b/, @$a Array Num array contains number grep $_ == $b, @$a Array Any array contains string grep $_ eq $b, @$a Any undef undefined !defined $a Any Regex pattern match $a =~ /$b/ Code() Code() results are equal $a−>() eq $b−>() Any Code() simple closure truth $b−>() # ignoring $a Num numish[!] numeric equality $a == $b Any Str string equality $a eq $b Any Num numeric equality $a == $b Any Any string equality $a eq $b + − this must be a code reference whose prototype (if present) is not "" (subs with a "" prototype are dealt with by the "Code()" entry lower down) * − that is, each element matches the element of same index in the other array. If a circular reference is found, we fall back to referential equality. ! − either a real number, or a string that looks like a number

    Разумеется, "код соответствия" не представляет собой настоящий код соответствия: он просто объясняет предполагаемое значение. В отличие от grep, оператор smart match будет замыкаться каждый раз, когда это возможно.

    Пользовательское сопоставление через перегрузку Вы можете изменить способ сопоставления объекта путем перегрузки оператора ~~ . Это превосходит обычную интеллектуальную семантику соответствия. См. overload .

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

    Если у нас есть две переменные $x и $y, можно ли их сравнить? Равны ли 1, 1.0 и 1.00? А как насчет "1.00"? Что больше - "foo" или "bar"?

    Два набора операторов сравнения

    В Perl существует два набора операторов сравнения. Так же, как с уже изученными нами бинарными операторами сложения (+), конкатенации (.) и повторения (x), здесь тоже оператор определяет, как ведут себя операнды и как они сравниваются.

    Вот эти два набора операторов:

    Числовое Строковое Значение == eq равно!= ne не равно < lt меньше > gt больше <= le меньше или равно >= ge больше или равно

    Операторы слева сравнивают числовые значения, а справа (в средней колонке) сравнивают значения, основываясь на ASCII таблице или на текущей локали.

    Рассмотрим несколько примеров:

    Use strict; use warnings; use 5.010; if (12.0 == 12) { say "TRUE"; } else { say "FALSE"; } В этом простейшем случае Perl выведет TRUE, так как оператор == сравнивает два числа, так что Perl"у не важно, записаны ли они как целые числа, или как числа с плавающей точкой.

    В следующем сравнении ситуация немного интереснее

    "12.0" == 12

    это выражение также истинно, ведь оператор Perl"а == конвертирует строку в число.

    2 < 3 истинно, так как < сравнивает два числа. 2 lt 3 также истинно, ведь 2 находистя перед 3 в таблице ASCII. 12 > 3 очевидно, истинно. 12 gt 3 вернет FALSE

    Возможно, с первого взгляда кому-то это покажется неожиданным, но если подумать, Perl ведь сравнивает строки посимвольно. Так что он сравнивает "1" и "3", и раз они отличаются и "1" стоит перед "3" в таблице ASCII, на этом этапе Perl решает, строковое значение 12 меньше, чем строковое значение 3.

    Всегда нужно быть уверенным, что сравниваешь значение именно так, как нужно!

    "foo" == "bar" будет истинно

    Также это выдаст предупреждение, если(!) предупреждения включены с помощью use warnings . Причина его в том, что мы используем две строки как числа в числовом сравнении ==. Как упоминалось в предыдущей части, Perl смотрит на строку, начиная с левого конца, и конвертирует ее в число, которое там находит. Поскольку обе строки начинаются с букв, они будут конвертированы в 0. 0 == 0, так что выражение истинно.

    С другой стороны:

    "foo" eq "bar" ложно

    Так что всегда нужно быть уверенным, что сравниваешь значение именно так, как нужно!

    То же будет при сравнении

    "foo" == "" будет истинно

    "foo" eq "" будет ложно

    Результаты в этой таблице могут пригодиться:

    12.0 == 12 ИСТИНА "12.0" == 12 ИСТИНА "12.0" eq 12 ЛОЖЬ 2 < 3 ИСТИНА 2 lt 3 ИСТИНА 12 > 3 ИСТИНА 12 gt 3 ЛОЖЬ! (внимание, может быть неочевидно с первого взгляда) "foo" == "" ИСТИНА! (Выдает предупреждение, если использована прагма "warnings") "foo" eq "" ЛОЖЬ "foo" == "bar" ИСТИНА! (Выдает предупреждение, если использована прагма "warnings") "foo" eq "bar" ЛОЖЬ

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

    Use strict; use warnings; use 5.010; print "input: "; my $name = ; chomp $name; if ($name == "") { # неверно! здесь нужно использовать eq вместо == ! say "TRUE"; } else { say "FALSE"; }

    Если запустить этот скрипт и ввести "abc", мы получим ответ TRUE, так как perl решил, что "abc" это то же, что и пустая строка.

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

    Простой оператор представляет собой любое выражение, завершенное точкой с запятой ";". Символ точка с запятой обязателен. Он может отсутствовать, только если простой оператор является последним оператором в блоке, специальной синтаксической конструкции, о которой мы поговорим чуть-чуть позже.

    Основное назначение простого оператора - вычисление выражения с побочным эффектом, который связан с изменением значения некоторых переменных в выражении при его вычислении. Обычно он реализуется операциями увеличения/уменьшения на единицу (++, --):

    $п++; # Переменная $п увеличивается на единицу. -$п**2; # Переменная $п уменьшается на единицу.

    Никакие другие операции Perl не вызывают побочных эффектов в выражении, если не считать операции присваивания (простое и составное), результатом вычисления которой является изменение значения левого операнда. Вызовы функций также могут приводить к побочным эффектам, но об этом подробнее мы расскажем в главе 11.

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

    ($n*$m)**4 + 6;

    Будет отображено сообщение

    Useless use of addition in void context at D:\PERL\EXAMPLE3.PL line 4.

    Отметим, что в сообщении упоминается о последней выполненной операции в выражении.

    Читатель спросит, какой прок в операторе, не выполняющем никакого действия. Его можно использовать для задания возвращаемого пользовательской функцией значения. Забегая вперед, скажем, что если в функции явно не указано в операторе return о возвращаемое значение, то по умолчанию Perl считает таковым значение последнего вычисленного оператора. Именно это обстоятельство и используется многими программистами для определения возвращаемого значения:

    Sub raySub {

    какие-то операторы condition == true ? "Успех" : "Провал"; # Последний оператор * "

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

    5.2. Модификаторы простых операторов

    Каждый простой оператор может быть снабжен модификатором, представляющим ключевое СЛОВО if, unless, while, until ИЛИ foreach, за которым следует выражение-условие. В самом операторе модификатор стоит непосредственно за выражением, составляющим простой оператор, перед завершающим символом точка с запятой. Каждый простой оператор может иметь только один модификатор. Семантически роль модификатора сводится к тому, что оператор вычисляется при выполнении условия, определяемого модификатором. Например, следующий оператор присваивания

    $n = $l/$m if $т!= 0;

    С модификатором if будет выполнен при условии, что переменная $т не равна о. Общий синтаксис простого оператора с модификатором имеет следующий вид:

    ВЫРАЖЕНИЕ ключ_слово_модификатора [(]ВЫРАЖЕНИЕ-УСЛОВИЕ [)];

    5.2.1. Модификаторы if и unless

    Модификаторы if и unless употребляются в прямом смысле их английского значения. Простой оператор с модификатором If выполняется, если ВЫРАЖЕНИЕ-УСЛОВИЕ истинно. Семантически простой оператор

    ВЫРАЖЕНИЕ if ВЫРАЖЕНИЕ-УСЛОВИЕ;

    Эквивалентен следующему оператору условия:

    if(ВЫРАЖЕНИЕ-УСЛОВИЕ) { ВЫРАЖЕНИЕ; }

    Модификатор unless является прямой противоположностью модификатора if: простой оператор выполняется, если ВЫРАЖЕНИЕ-УСЛОВИЕ не истинно. Общий синтаксис простого оператора с модификатором unless имеет следующий вид:

    ВЫРАЖЕНИЕ unless ВЫРАЖЕНИЕ-УСЛОВИЕ;

    Это всего лишь удобная форма записи оператора условия

    if(! ВЫРАЖЕНИЕ-УСЛОВИЕ) { ВЫРАЖЕНИЕ; }

    Использование модификаторов if и unless показано в примере 5.1 - простой программе решения квадратного уравнения.

    # peri -w

    # Решение квадратного уравнения а*х**2+Ь*х+с=0

    $а = ;

    $b = ;

    $с = ;

    $d = $b**2 - 4*$a*$c; # Вычисление дискриминанта уравнения

    # Вычисление корней, если дискриминант положителен

    ($xl =.(-$b+sqrt $d)/$a/2, $x2 = (-$b-sqrt $d)/$a/2) unless $d < 0;

    # Печать результатов

    Print "Коэффициенты:\п а = $а b = $b с = $с"; print "\tPenieHHe:\n\t$xl\t$x2" if defined $xl; print "^Решения нет!" unless defined $xl;

    Наша программа решения квадратного уравнения, конечно, примитивна. Из всех возможных проверок в ней проверяется на положительность только дискриминант квадратного уравнения, хотя стоило бы проверить на нуль значение вводимого пользователем с клавиатуры старшего коэффициента уравнения, сохраняемого в переменной $а.

    Модификатор unless используется в операторах вычисления корней и печати сообщения об отсутствии решения. Обратите внимание, что в операторе печати проверяется, определена ли переменная $xi, а будет она определена только в случае положительности дискриминанта $d. В модификаторе if оператора печати корней уравнения также проверяется, определена ли переменная $xl.

    5.2.2. Модификаторы while и until

    Эти два модификатора немного сложнее модификаторов if и unless. Они реализуют процесс циклического вычисления простого оператора. Их синтаксис таков:

    ВЫРАЖЕНИЕ while ВЫРАЖЕНИЕ-УСЛОВИЕ; ВЫРАЖЕНИЕ until ВЫРАЖЕНИЕ-УСЛОВИЕ;

    Модификатор while повторно вычисляет ВЫРАЖЕНИЕ, пока истинно ВЫРАЖЕНИЕ-УСЛОВИЕ. Модификатор until противоположен модификатору while: ВЫРАЖЕНИЕ повторно вычисляется до момента, когда ВЫРАЖЕНИЕ-УСЛОВИЕ станет истинным, иными словами оно вычисляется, пока ВЫРАЖЕНИЕ-УСЛОВИЕ ложно.

    Семантически эти модификаторы простых операторов эквивалентны следующим составным операторам цикла:

    while(ВЫРАЖЕНИЕ-УСЛОВИЕ) { ВЫРАЖЕНИЕ; } until(ВЫРАЖЕНИЕ-УСЛОВИЕ) { ВЫРАЖЕНИЕ; }

    Пример 5.2 дает представление о том, как работают модификаторы повтора while И until.

    # peri -w $first = 10;

    $second = 10; $first++ while $first < 15; # $first увеличивается, пока не станет

    # равной 15

    -$second until $second < 5; # $second уменьшается, пока не станет

    # равной 4

    print "\$first $first\n"; print "\$second $second\n";

    Оператор увеличения на единицу переменной $first будет выполняться, пока выражение $ first < 15 остается истинным. Когда значение переменной $first станет равным 15, выражение модификатора while становится ложным, и оператор завершает работу. Аналогично работает и следующий оператор уменьшения переменной $second на единицу. Единственное отличие от предыдущего оператора заключается в том, что он выполняется, пока выражение $ second < 5 модификатора until остается ложным. Два оператора печати выведут на экран значения переменных $first и $second равными соответственно 15 и 4.

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

    Существует единственное исключение из этого правила, когда модификаторы повтора применяются к синтаксической конструкции do <}, которая не является оператором (хотя внешне и похожа), а относится к термам (см. главу 4). Поэтому, если ее завершить точкой с запятой, то такая конструкция будет являться простым оператором, к которому можно применять все возможные модификаторы Perl. Семантика этой конструкции заключается в том, что она вычисляет операторы, заданные в фигурных скобках {}, и возвращает значение последнего выполненного оператора. Так вот, если к простому оператору do {}; применить модификаторы повтора, то сначала выполнятся операторы конструкции do {}, а потом будет проверено условие модификатора. Это позволяет написать следующий простой оператор, который сначала осуществит ввод с клавиатуры, а потом проверит введенную информацию на совпадение с символом завершения ввода:

    $string = ""; do{

    $line = ;

    $string .= $line; I until $line eq ".\n";

    Этот фрагмент кода будет накапливать вводимые пользователем строки в переменной $string до тех пор, пока не будет введена строка, состоящая из единственного символа точки, после чего оператор do{} until; завершит свою работу. Обратите внимание, что проверка в модификаторе until ведется на совпадение со строкой ". \п", в которой присутствует символ перехода на новую строку. Дело в том, что операция ввода передает этот символ в программу, так как пользователь именно этим символом завершает ввод строки (нажатие клавиши ).

    5.2.3. Модификатор foreach

    Модификатор foreach ВЫРАЖЕНИЕ относится к модификаторам цикла. Он повторно выполняет простой оператор, осуществляя итерации по списку значений, заданному в ВЫРАЖЕНИЕ. На каждой итерации выбранный элемент списка присваивается встроенной переменной $_, которую можно использовать в простом операторе для получения значения выбранного элемента списка. Например, следующий оператор распечатает все элементы массива @т:

    Print "$_ " foreach @т;

    Общий синтаксис простого оператора с модификатором foreach следующий:

    ВЫРАЖЕНИЕ foreach ВЫРАЖЕНИЕ-СПИСОК;

    Простой оператор с модификатором foreach всего лишь удобная форма записи составного оператора jforeach:

    foreach (ВЫРАЖЕНИЕ-СПИСОК) { ВЫРАЖЕНИЕ; }

    Эта форма составного оператора foreach в качестве переменной цикла использует встроенную переменную $_ (см. раздел 5.4.3). Обратим внимание читателя на то, что ВЫРАЖЕНИЕ-список вычисляется в списковом контексте, поэтому все используемые в нем переменные ведут себя так, как они должны вести в списковом контексте. Например, хеш-массив представляет обычный список, составленный из последовательности его пар ключ/значение. Следующий фрагмент кода

    %hash = (one=>6, two=>8, three=>10); print "$_ " foreach %hash;

    Напечатает строку

    Three 10 two 8 one 6

    Эта строка и есть тот простой список, который возвращает хеш в списковом контексте.

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

    # peri -w

    §array = (1, 2, 3);

    $_ *= 2 foreach Sarray; # Умножение каждого элемента на 2.

    print "@array"; # Напечатает строку: 246

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

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

    5.3.1. Блоки

    Блок - последовательность операторов, определяющая область видимости переменных. В программе блок обычно ограничен фигурными скобками {...}. Определяя синтаксис составных операторов, мы будем иметь в виду именно такой блок - последовательность операторов в фигурных скобках и обозначать его БЛОК. Интерпретатор рассматривает БЛОК как один оператор, вычисляемым значением которого является значение последнего выполненного оператора блока. Это означает, что там, где можно использовать один оператор, можно использовать и БЛОК. Такая ситуация встречается при использовании функции тар(). Она выполняет определяемый ее первым параметром оператор для всех элементов списка, заданного вторым параметром. Значение каждого элемента списка при вычислениях временно присваивается встроенной переменной $_. Возвращает эта функция список вычисленных значений оператора:

    @rez = map $_ **= 2, @array; # Список квадратов элементов массива.

    В качестве первого параметра этой функции можно использовать БЛОК. Следующий оператор также вычисляет список квадратов элементов массива @аггау, одновременно подсчитывая количество его элементов:

    @rez = map { ++$kol; $_ **= 2} @array; # Список квадратов элементов

    # массива и подсчет их количества.

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

    Как сказано в начале этого раздела, блок определяет область видимости переменных. Это означает, что в блоке можно создать переменные, обращаться к которым можно только из операторов, расположенных в этом блоке. Пока мы в блоке, мы можем присваивать им новые значения, использовать в вычислениях и т. п., но как только мы вышли из блока, мы теряем с ними "связь", они становятся "не видимыми". Такие переменные еще называют локальными переменными.

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

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

    (Более подробно лексические и динамические переменные рассматриваются в главе 11.)

    Локальные переменные удобны для создания временных переменных, которые нигде больше не будут использоваться в программе, а только в одном определенном месте. Например, при отладке части кода часто приходится создавать временные переменные и выводить на печать их значения. Локальные переменные могут иметь такие же имена, как и глобально используемые переменные. Это не приводит к конфликту. После завершения операторов блока значение глобальной переменной имеет то же значение, которое она имела до начала выполнения операторов блока (пример 5.4).

    # peri -w

    $var = "outer"; # Глобальная переменная $var $glob = "glob"; # Глобальная переменная $glob my $lex = "outer_l"; # Лексическая переменная $1ех {

    my($var) = "inner"; # Внутренняя переменная $var my($varl) = "inner_l"; # Внутренняя переменная $varl print "В блоке \$var = $var\n"; # Напечатает inner print "В блоке \$varl = $varl\n"; # Напечатает inner_l print "В блоке \$lex = $lex\n"; # Напечатает outer_l print "В блоке \$glob = $glob\n"; # Напечатает glob }

    print "Вне блока \$var = $var\n"; # Напечатает outer print "Вне блока \$1ех = $lex\n"; # Напечатает outer_l print "Вне блока \$varl = $varl\n"; # Напечатает пустую строку ""

    Программа примера 5.4 демонстрирует области видимости лексических переменных. Внутри блока {...} "видны" переменные, созданные вне блока: и глобальные, и лексические ($giob, $iex), если только они не переопределены внутри блока ($var). При выходе из внутреннего блока восстанавливаются значения переменных, которые были переопределены внутри блока ($var). Доступ к локальным переменным блока извне невозможен ($vari).

    5.3.2. Операторы ветвления

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

    Эти операторы вычисляют выражение, называемое условием, и в зависимости от его истинности или ложности выполняют или не выполняют некоторый блок операторов. Это означает, что выражения условия во всех операторах ветвления вычисляются в булевом контексте.

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

    В языке существует три формы оператора ветвления if:

    if (ВЫРАЖЕНИЕ) БЛОК

    if (ВЫРАЖЕНИЕ) БЛОК1 else БЛОК2

    if (ВЫРАЖЕНИЕ!) БЛОК1 elsif (ВЫРАЖЕНИЕ2) БЛОК2 ... else БЛОКп

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

    Первый оператор if реализует простейшее ветвление. Если ВЫРАЖЕНИЕ истинно, то выполняются операторы из БЛОК, в противном случае БЛОК просто пропускается:

    $var = 10;

    If ($var -= 5) {

    print "Переменная \$var - $var"; }

    Обратите внимание, что в этом примере ВЫРАЖЕНИЕ представляет операцию составного присваивания. Это может показаться необычным, так как в большинстве языков программирования здесь требуется выражение, возвращающее булево значение. В Perl можно использовать любое выражение, в том числе и присваивание. Результат его вычисления интерпретируется в булевом контексте: если вычисленное значение равно о или пустой строке "", то оно трактуется как Ложь, иначе - Истина. Возвращаемым значением операции присваивания является значение, присвоенное переменной левого операнда. В нашем примере это число 5, следовательно в булевом контексте оно трактуется как Истина, а поэтому оператор печати print будет выполнен. Если перед выполнением оператора if переменная $var будет равняться 5, то выражение условия будет вычислено равным Ложь и все операторы блока будут просто пропущены.

    Обычно выражение условия представляет собой сложное выражение, составленное из операций отношения, связанных логическими операциями. Использование операции присваивания в выражении условия оператора if не совсем типично. Здесь мы его использовали, чтобы подчеркнуть то обстоятельство, что в Perl любое правильное выражение может быть использовано в качестве выражения условия, которое вычисляется в булевом контексте. Вторая форма оператора if используется, когда необходимо выполнить одну группу операторов (БЛОК!) в случае истинности некоторого выражения (ВЫРАЖЕНИЕ), а в случае его ложности - другую группу операторов (влок2):

    If ($var >= 0} # ВЫРАЖЕНИЕ {

    Print "Переменная неотрицательна."; # БЛОК1, если ВЫРАЖЕНИЕ истинно } else {

    Print "Переменная отрицательна."; # БЛОК2, если ВЫРАЖЕНИЕ ложно }

    По существу, первая форма оператора if эквивалентна второй форме, если БЛОК2 не содержит ни одного оператора.

    Последняя, третья форма оператора if реализует цепочку ветвлений. Семантика этого оператора такова. Выполняются операторы из БЛОК!, если

    ИСТИННО ВЫРАЖЕНИЕ!. ЕСЛИ ОНО ЛОЖНО, ТО ВЫПОЛНЯЮТСЯ Операторы ИЗ БЛОК2

    В случае истинности вырлжЕНИЕ2. Если и оно ложно, то проверяется ВЫРАЖЕ-НИЕЗ и т. д. Если ни одно из выражений условия оператора if не истинно, то выполняются операторы блока, определяемого после ключевого слова else в случае его наличия. В противном случае выполняется следующий после оператора if оператор программы. При выполнении следующего оператора ветвления if

    if($var < 0) { # ВЫРАЖЕНИЕ!

    print "Переменная отрицательна"; i БЛОК! } elsif ($var == 0) { # ВЫРАЖЕНИЕ2

    Сначала проверяется условие отрицательности переменной $var. Если значение переменной строго меньше нуля (ВЫРАЖЕНИЕ1), то печатается сообщение из БЛОК! и оператор завершает свою работу. Если значение переменной не меньше нуля, то оно проверяется на равенство (ВЫРАЖЕНИЕ2) и в случае истинности выполняется оператор печати из блока операторов elsif (влок2). Если проверка на равенство нулю дала ложный результат, то выполняется оператор печати из блока операторов else (БЛОКЗ).

    В операторе if со множественными проверками может быть сколько угодно

    блоков elsif, НО ТОЛЬКО ОДИН бЛОК else.

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

    При работе с операторами ветвления важно помнить, что только один блок операторов будет выполнен - тот, для которого истинно соответствующее выражение условия.

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

    unless($var >= 0} { # ВЫРАЖЕНИЕ!

    print "Переменная отрицательна"; # БЛОК! } elsif ($var == 0) { # ВЫРАЖЕНИЕ2

    print "Переменная равна нулю"; # БЛОК2 } else {

    print "Переменная положительна"; # БЛОКЗ }

    При этом нам пришлось заменить ВЫРАЖЕНИЕ! на противоположное по смыслу.

    5.4. Операторы цикла

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

    Мы уже познакомились с операторами ветвления Perl, а теперь пришло время узнать, какие конструкции цикла можно применять в Perl. Их всего три: while, for и foreach. Все они относятся к классу составных операторов и, естественно, определяются в терминах блоков БЛОК.

    5.4.1. Циклы while и until

    Цикл while предназначен для повторного вычисления блока операторов, пока остается истинным задаваемое в нем выражение-условие. Его общий синтаксис имеет две формы:

    МЕТКА while (ВЫРАЖЕНИЕ) БЛОК

    МЕТКА while (ВЫРАЖЕНИЕ) БЛОК continue БЛОК1

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

    Оператор while выполняется по следующей схеме. Вычисляется выражения-условия ВЫРАЖЕНИЕ. Если оно истинно, то выполняются операторы БЛОК. В противном случае оператор цикла завершает свою работу и передает управление следующему после него оператору программы (цикл 1 примера 5.5). Таким образом, оператор цикла while является управляющей конструкцией цикла с предусловием: сначала проверяется условие завершения цикла, а потом только тело цикла, определяемое операторами БЛОК. Поэтому может оказаться, что тело цикла не будет выполнено ни одного раза, если при первом вхождении в цикл условие окажется ложным (цикл 3 примера 5.5).

    Вместо ключевого слова while можно использовать ключевое слово until. В этом случае управляющая конструкция называется циклом until, который отличается от разобранного цикла while тем, что его тело выполняется, только если выражение условия ложно (цикл 2 примера 5.5).

    # peri -w

    # цикл 1

    $i = 1;

    while <$i <= 3) {

    ++$i; >

    print "Переменная цикла \$i = $i\n"; # $i = 4 print "Массив \@a: @a\n"; # @a = (I, 0.5. 0.333333333333333)

    # цикл 2, эквивалентный предыдущему

    $i = 1;

    until ($i > 3) {

    $a[$i] = l/$i; # Присвоить значение элементу массива

    ++$i; }

    Print "Переменная цикла \$i = $i\n"; # $i = 4 print "Массив \@a: @a\n"; # @a = (1, 0.5. 0.333333333333333)

    # цикл З, тело цикла не выполняется ни одного раза

    $i = 5;

    While ($i-<= 3) {

    $a[$i] = l/$i;

    ++$i; } print "Переменная цикла \$i = $i\n"; # $i = 5

    # цикл 4, бесконечный цикл (не изменяется выражение условия)

    $i = 1;

    While ($i <= 3) {

    $a[$i] = l/$i; } .

    Обратим внимание на то, что в теле цикла должны присутствовать операторы, вычисление которых приводит к изменению выражения условия. Обычно это операторы, изменяющие значения переменных, используемых в выражении условия. Если этого не происходит, то цикл while или until будет выполняться бесконечно (цикл 4 примера 5.5).

    Блок операторов БЛОК!, задаваемый после ключевого слова continue, выполняется всякий раз, когда осуществляется переход на выполнение новой итерации. Это происходит после выполнения последнего оператора тела цикла или при явном переходе на следующую итерацию цикла командой next. Блок continue на практике используется редко, но с его помощью можно строго определить цикл for через оператор цикла while.

    Пример 5.6 демонстрирует использование цикла while для вычисления степеней двойки не выше шестнадцатой. В этом примере оператор цикла while функционально эквивалентен циклу for. Блок continue выполняется всякий раз по завершении очередной итерации цикла, увеличивая переменную $i на единицу. Он эквивалентен выражению увеличения/уменьшения оператора for (см. следующий раздел).

    # peri -w

    # Вычисление степеней числа 2 $1 = I;

    while ($i <= 16) {

    print "2 в степени $i: ", 2**$i, "\n"; } continue {

    ++$i; f Увеличение переменной $i перед выполнением следующей итерации }

    5.4.2. Цикл for

    При выполнении циклов while и until заранее не известно, сколько итераций необходимо выполнить. Их количество зависит от многих факторов: значений переменных в выражении условия до начала выполнения цикла, их изменении в теле цикла, виде самого выражения условия и т. п. Но иногда в программе необходимо выполнить заранее известное количество повторений определенной группы операторов. Например, прочитать из файла 5 строк и видоизменить их по определенным правилам. Конечно, можно такую задачу запрограммировать операторами цикла while и until,

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

    МЕТКА for (ВЫРАЖЕНИЕ!; ВЫРАЖЕНИЕ2; ВЫРАЖЕНИЕЗ) БЛОК

    ВЫРАЖЕНИЕ! используется для установки начальных значений переменных, управляющих циклом, поэтому его называют инициализирующим выражением. Обычно это одна или несколько операций присваивания, разделенных запятыми.

    ВЫРАЖЕНИЕ2 определяет условие, при котором будут повторяться итерации цикла. Оно, как и выражение-условие цикла while, должно быть истинным, чтобы началась следующая итерация. Как только это выражение становится ложным, цикл for прекращает выполняться и передает управление следующему за ним в программе оператору.

    ВЫРАЖЕНИЕЗ отвечает за увеличение/уменьшение значений переменных цикла после завершения очередной итерации. Обычно оно представляет собой список выражений с побочным эффектом или список операций присваивания переменным цикла новых значений. Его иногда называют изменяющим выражением.

    Алгоритм выполнения цикла for следующий:

    1. Вычисляется инициализирующее выражение (ВЫРАЖЕНИЕ!).

    2. Вычисляется выражение условия (вырАЖЕШЕ2). Если оно истинно, то выполняются операторы блока БЛОК, иначе цикл завершает свое выполнение.

    3. После выполнения очередной итерации вычисляется выражение увеличения/уменьшения (ВЫРАЖЕНИЕЗ) и повторяется пункт 2.

    Как отмечалось в предыдущем разделе, цикл for эквивалентен циклу while с блоком continue. Например, следующий цикл

    For ($i = 1; $i .<= 10; $i++) { }

    Эквивалентен циклу while

    $i =1;

    While ($i <= 10) {

    } continue {

    $i++; }

    Существует единственное отличие между этими двумя циклами. Цикл for определяет лексическую область видимости для переменной цикла. Это позволяет использовать в качестве переменных цикла локальные переменные, объявленные с помощью функции ту:

    $i = "global";

    for (my $i = 1; $i <= 3; $i++) {

    print "Внутри цикла \$i: $i\n"; } print "Вне цикла \$i: $i\n ";

    При выполнении этого фрагмента программы оператор печати будет последовательно отображать значения 1, 2 и з локальной переменной цикла $1. При выходе из цикла локальная переменная $i будет уничтожена и оператор печати вне цикла напечатает строку global - значение глобальной переменной $1, определенной вне цикла for.

    Все три выражения цикла for являются необязательными и могут быть опущены, но соответствующие разделители ",-" должны быть оставлены. Если опущено выражение условия, то по умолчанию оно принимается равным Истина. Это позволяет организовать бесконечный цикл:

    For (;;) {

    }

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

    Инициализировать переменную цикла можно и вне цикла, а изменять значение переменной цикла можно и внутри тела цикла. В этом случае инициализирующее и изменяющее выражения не обязательны:

    $i = 1;

    For ( ; $i <= 3;) {

    $i++; }

    Совет

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

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

    Жениях используется операция запятая. Например, если мы хотим создать хеш, в котором ключам, представляющим цифры от 1 до 9, соответствуют значения этих же цифр в обратном порядке от 9 до 1, то эту задачу можно решить с помощью цикла for с двумя переменными цикла:

    for ($j = 1, $k = 9; $k >0; $j++, $k-) {

    $hash{$j} = $k; }

    Этот же пример показывает, что в цикле for переменная цикла может как увеличиваться, так и уменьшаться. Главное, чтобы выражение условия правильно отслеживало условия продолжения итераций цикла.

    Цикл for достаточно гибкая конструкция, которую можно использовать не только для реализации цикла с заранее заданным числом итераций. Он позволяет в инициализирующем и изменяющем выражениях использовать вызовы встроенных и пользовательских функций, а не только определять и изменять переменные цикла. Основное - чтобы изменялось выражение условия завершения цикла. Пример 5.7 демонстрирует именно такое использование цикла for.

    # peri -w

    for (print "Введите данные, для завершения ввода нажмите \n"; ;

    print "Введите данные, для завершения ввода нажмите \n") {

    last if $_ eq "\n"; print "Ввели строку: $_"; }

    В этом примере пользователь вводит в цикле строки данных. Перед вводом новой строки отображается подсказка с помощью функции print (), которая определена в изменяющем выражении цикла. Выражение условия представляет операцию ввода из файла стандартного ввода . Так как это выражение вычисляется всякий раз, когда цикл переходит на очередную итерацию, то на каждом шаге цикла программа будет ожидать ввода с клавиатуры. Выход из цикла осуществляется командой last, вызываемой в случае ввода пользователем пустой строки. Введенные данные сохраняются во встроенной переменной $_, причем в ней сохраняется и символ перехода на новую строку, являющийся признаком завершения операции ввода данных. Поэтому при вводе пустой строки на самом деле в переменной $_ хранится управляющая последовательность "\п", с которой и осуществляется сравнение для реализации выхода из цикла.

    Пример 5.8 демонстрирует программу, читающую 3 строки файла егг.егг. Операция чтения из файла задается в инициализирующем и изменяющем выражении вместе с определением и изменением переменной цикла $1.

    # peri -w

    open (FF, "err.err") or die "Ошибка открытия файла";

    for ($line=, $count = 1; $count <=3; $line=, $count++)

    {

    print "Строка $count:\n $line\n";

    t " }

    close(FILE);

    5.4.3. Цикл foreach

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

    #! peri -w

    @array = (1,-6,9,18,0,-10);

    $max = $array; ,

    for ($i = 1; $i <= $farray; $i++) {

    $max = $array[$i] if $array[$i] > $max; }

    После выполнения программы примера 5.9 переменная $max будет иметь значение 18, равное максимальному элементу массива $аггау. Обратим внимание читателя на то, что в цикле for (как и в цикле while) доступ к элементам массива организуется с помощью индекса.

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

    МЕТКА foreach ПЕРЕМЕННАЯ (СПИСОК) БЛОК

    МЕТКА foreach ПЕРЕМЕННАЯ (СПИСОК) БЛОК continue БЛОК

    Он реализует цикл по элементам списка список, присваивая на каждом шаге цикла переменной ПЕРЕМЕННАЯ значение выбранного элемента списка. Блок операторов continue выполняется всякий раз, как начинается очередная итерация, за исключением первой итерации, когда переменная $temp равна первому элементу списка. Список можно задавать или последовательностью значений, разделенных запятыми, или массивом скаляров, или функцией, возвращаемым значением которой является список. Определение максимального элемента массива можно переписать с циклом foreach (пример 5.10).

    #! peri, -w

    Sarray = (1,-6,9,18,0,-10) ; $max = $array; foreach $temp (Sarray) (

    $max = $temp if $temp > $max; } print "$max";

    На каждом шаге цикла переменная $temp последовательно принимает значения элементов массива $аггау. Обратите внимание на внешний вид программы - в отсутствии индексов массива она стала лучше читаемой.

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

    For $temp (@array) { # Ключевое слово foreach синоним for.

    $max = $temp if $temp > $max; }

    Однако, как нам кажется, использование foreach лучше отражает семантику этого оператора цикла, так как в самом ключевом слове уже отражена его сущность (for each - для каждого).

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

    Обычно программисты, работающие на языке Perl, вообще не применяют в циклах foreach переменную цикла. Это связано с тем обстоятельством, что в отсутствии явно заданной переменной цикла Perl по умолчанию использует специальную переменную $_. На каждом шаге цикла именно она будет содержать значение элемента списка или массива. С учетом этого факта цикл foreach примера 5.10 можно переписать так:

    foreach (@array) { # В качестве переменной цикла используется $_.

    $гоах = $_ if $_ > $max;

    } . l

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

    Foreach $temp (@array) {

    $temp **= 2; }

    Список, по элементам которого организуется цикл, может быть задан не только явно конструктором или переменной массива, но и функцией, возвращаемым значением которой является список. Канонический способ печати хеш-массива в упорядоченном порядке представлен в примере 5.11.

    # peri -w %array = {

    blue => 1,

    red => 2,

    green => 3,

    yellow => 3); foreach (sort keys %array) {

    print "$_\t => $array{$_}\n"; } "

    Эта программа напечатает пары ключ/значение хеш-массива %аггау в соответствии с алфавитным порядком его ключей:

    blue => 1

    green => 3

    red => 2

    Yellow => 3

    5.5. Команды управления циклом

    Каждый цикл в программе завершается при достижении некоторого условия, определяемого самим оператором. В циклах while и for это связано с ложностью выражения-условия, а в цикле foreach с окончанием перебора всех элементов списка. Иногда возникает необходимость при возникновении некоторых условий завершить выполнение всего цикла, либо прервать выполнение операторов цикла и перейти на очередную итерации. Для подобных целей в языке Perl предусмотрены три команды last, next и redo, которые и называют командами управления циклом.

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

    last ИДЕНТИФИКАТОР_МЕТКИ; next ИДЕНТИФИКАТОР_МЕТКИ; redo ИДЕНТИФИКАТОР_МЕТКИ;

    Семантика этих команд также проста. Они изменяют порядок выполнения циклов, принятый по умолчанию в языке, и передают управление в определенное место программы, завершая выполнение цикла (last), переходя на следующую итерацию цикла (next) или повторяя выполнение операторов тела цикла при тех же значениях переменных цикла (redo). Место перехода задается меткой. Помните синтаксис операторов цикла? Каждый из них может быть помечен. Именно идентификаторы меток операторов цикла и используются в командах управления для указания места передачи управления.

    Метка в программе Perl задается идентификатором, за которым следует двоеточие. В командах управления циклом используется именно идентификатор метки, а не метка.

    Несколько слов о терминологии. Читатель, наверное, обратил внимание, что мы не называем команды управления циклом операторами. И это справедливо. Они не являются операторами, хотя могут использоваться как операторы. Их следует считать унарными операциями, результатом вычисления которых является изменение последовательности выполнения операторов. Поэтому команды управления циклом можно использовать в любом выражении Perl. Заметим, что их следует использовать в таких выражениях, где имеет смысл их использовать, например в выражениях с операцией "запятая":

    Open (INPUT_FILE, $file)

    or warn ("Невозможно открыть $file: $!\n"), next FILE;

    Приведенный оператор может являться частью программы, которая в цикле последовательно открывает и обрабатывает файлы. Команда next инициирует очередную итерацию цикла с меткой FILE, если не удалось открыть файл в текущей итерации. Обратите внимание, что она используется в качестве операнда операции "запятая". В таком контексте эта команда имеет смысл. Следующий оператор является синтаксически правильным, но использование в нем команды redo не имеет никакого смысла:

    Print "qu-qu", 5 * redo OUT, "hi-hi\n";

    Результатом выполнения этого оператора будет повторение вычислений операторов цикла с меткой ODT, т. е. простое выполнение команды redo OUT.

    Относительно команд управления циклом следует сказать, что к ним можно применять модификаторы, так как употребленные самостоятельно с завершающей точкой с запятой они рассматриваются как простые операторы: next if $a - 2;

    Переход на следующую итерацию цикла осуществится только, если переменная $а равна 2.

    5.5.1. Команда last

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

    #! peri -w

    @letters = ("A".."Z");

    for ($index=0; $index<01etters; $index++) {

    last if $letters[$index] eq "M"; } print $index;

    Цикл в программе примера 5.12 будет выполняться, пока перебор элементов массива $ letters не достигнет элемента, содержащего символ "м". После чего будет выполнен первый после оператора for оператор программы. В результате будет напечатано число 12 - индекс элемента, содержащего символ "м".

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

    CYCLE_1: while (...){ , CYCLE_2: for (...) {

    CYCLE_3: foreach (...) { last CYCLE_2; }

    Операторы цикла CYCLE_2 } Операторы цикла CYCLE_1 # Сюда передает управление

    t оператор last CYCLE_2; }

    Если в команде last указать метку CYCLE_I, то управление будет передано на первый после самого внешнего цикла оператор программы. Если в команде last задать метку CYCLE_S (или задать ее вообще без метки), то управление будет передано на первый оператор группы операторы цикла CYCLE_2.

    Передача управления командой last осуществляется не на оператор цикла с соответствующей меткой, а на оператор, непосредственно следующий за ним.

    Команда last осуществляет выход из цикла, не выполняя никаких блоков операторов continue.

    5.5.2. Команда next

    Команда next позволяет пропустить расположенные после нее в теле цикла операторы и перейти на следующую итерацию цикла. Если оператор цикла содержит блок continue, то его операторы выполняются до проверки условия окончания цикла, с которой начинается следующая итерация. Одно из применений этой команды - обработать определенные элементы массива, ничего не делая с другими. Программа примера 5.14 присваивает всем элементам массива, содержащим четные числа, символ звездочка "*".

    #! peri -w

    @array = (2, 5, 8, 4, 7, 9); print "До: @array\n"; fоreach (Sarray) { next if $_ % 2;

    $_ = »*»;

    }

    print "После: @array\n";

    Результат выполнения программы примера 5.14 показан ниже:

    До: 2 5 8 4 7 9 После: * 5 * * 7 9

    Если элемент массива нечетное число, то результат операции $_ % 2 равен i (Истина) и команда next инициирует следующую итерацию цикла foreach, не изменяя значение текущего элемента массива. Если значением элемента массива является четное число, то команда next не выполняется и значение элемента меняется на символ "*".

    Команда next, употребленная совместно с идентификатором метки прерывает выполнение цикла, в теле которого она находится, и начинает новую итерацию цикла с указанной меткой, выполнив предварительно его блок continue, если таковой имеется (пример 5.15).

    #! peri -w

    $out =- 0;

    OUT: while ($out < 2) {

    print "Начало внешнего цикла\п";

    for($in=0; $in<=2; $in++) {

    print "\$out: $out\t\$in: $in\n"; next OUT if $in =1; }

    print "\$out: $out\n"; # Никогда не выполняется! } continue {

    print "Блок continue внешнего цикла\п"; $out++; }

    Вывод этой программы будет следующим:

    Начало внешнего цикла

    $out: 0 $in: О

    $out: 0 $in: 1

    Блок continue внешнего цикла

    Начало внешнего цикла

    $out: I $in: О

    $out: I $in: 1

    Блок continue внешнего цикла

    Обратите внимание, что количество итераций внутреннего цикла for равно двум, так как на второй его итерации выполняется команда next OUT, прекращающая его выполнение и инициализирующая выполнение очередной итерации внешнего цикла OUT. Оператор печати этого цикла пропускается, выполняется блок операторов continue, проверяется условие и если оно истинно, то тело цикла выполняется. Таким образом, оператор печати внешнего цикла OUT не выполняется ни одного раза, что подтверждается приведенным выводом из программы примера 5.15.

    5.5.3. Команда redo

    Команда redo повторно выполняет операторы тела цикла, не инициализируя следующую итерацию. Это означает, что ни выражение изменения цикла for, ни операторы блока continue, если он присутствует, ни выражение условия не вычисляются. Операторы тела цикла, расположенные за оператором redo, пропускаются и снова начинается выполнение тела цикла со значениями переменных, которые они имели перед выполнением этой передачи управления. Программа примера 5.16 демонстрирует использование команды redo.

    I! peri -w $notempty = 0;

    $total = 0;

    for (;;) { tt Бесконечный цикл

    $line=; # Ввод строки

    chop($line);

    last if $line eq "END"; # Выход из цикла

    ++$total;

    redo if $line eq ""; # Возврат на чтение строки

    ++$notempty; } print "Всего прочитано строк: $total\nM3 них не пустых: $notempty\n";

    Эта программа в бесконечном цикле ожидает ввода пользователем на клавиатуре строки данных и в переменной $ total подсчитывает количество введенных строк. В переменной $notempty вычисляется количество введенных не пустых строк. Если введена пустая строка, то команда redo начинает повторное выполнение операторов тела цикла, не увеличивая на единицу переменную $notempty. Для завершения бесконечного цикла следует ввести строку END. В этом случае выполняется команда last.

    Функция chop используется для удаления из введенной пользователем строки символа перехода на новую строку "\п", поэтому в программе она сравнивается со строками без завершающего символа перехода на новую строку (сравни с примером 5.7).

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

    #! peri -w $notempty = 0; $total = 0; OUT: while (1) {

    Print "Введи строки\п"; # Сюда передает управление команда redo OUT; for {;;) {

    $line=;

    chop($line);

    last OUT if-$line eq "END"; I Выход из всех циклов

    ++$total;

    Redo OUT if $line eq "";

    ++$notempty; } } print "Всего прочитано строк: $tptal\nH3 них не пустых: $notempty\n";

    В примере 5.17 мы ввели внешний бесконечный цикл OUT и изменили команды redo и last, добавив к ним метку на внешний цикл. Теперь в случае, если пользователь вводит пустую строку, команда redo OUT передает управление на первый оператор внешнего цикла, и программа печатает приглашение ввести строки.

    5.6. Именованные блоки

    В Perl блок операторов, заключенный в фигурные скобки, семантически эквивалентен циклу, выполняющемуся только один раз. В связи с этим обстоятельством можно использовать команду last для выхода из него, а команду redo для повторного вычисления операторов блока. Команда next также осуществляет выход из блока, но отличается от команды last тем, что вычисляются операторы блока continue, который может задаваться для блока операторов в фигурных скобках:

    BLOCK1: {

    $i = 1;

    Last BLOCK1; } continue {

    ++$i; }

    print "Переменная \$i после BLOCK1: $i\n"; BLOCK2: {

    $i = 1;

    Next BLOCK2; } continue {

    ++$i; } print "Переменная \$i после BLOCK2: $i\n";

    Первый оператор print этого фрагмента кода напечатает значение переменной $i равным г, тогда как второй оператор print напечатает 2, так как при

    Выходе из блока BLOCK2 будет выполнен оператор увеличения на единицу переменной $i из блока continue.

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

    #! peri -w $var = 3; SWITCH: {

    $casel = 1, last SWITCH if $var == 1;

    $case2 = 1, last SWITCH if $var == 2;

    $case3 = 1, last SWITCH if $var = 3;

    $nothing = 1; }

    После выполнения именованного блока операторов SWITCH переменная $casei будет равна 1, если $var равна i, $case2 будет равна 2, если $var равна 2 и, наконец, $case3 будет равна з, если $var равна з. В случае, если переменная $var не равна ни одному из перечисленных значений, то переменная $nothing будет равна i. Конечно, это простейший переключатель, разработанный всего лишь для демонстрации возможности быстрого создания переключателя в Perl. Для выполнения группы операторов в переключателе можно использовать не модификатор if, а оператор выбора if.

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

    $notempty = 0; $total = 0; INPUT: {

    $line=; chop($line);

    last INPUT if $line eq "END"; # Выход из бесконечного цикла ++$total;

    redo INPUT if $line eq ""; ++$notempty; redo INPUT; }

    Узнаете программу примера 5.16? Действительно, это реализация без оператора цикла программы ввода строк и подсчета общего числа введенных, а также непустых строк. Единственное, что нам пришлось добавить - еще одну команду redo в конце блока операторов.

    5.7. Оператор безусловного перехода

    Оператор безусловного перехода goto, возможно, самый спорный оператор. Много копий было поломано в дебатах о его целесообразности и полезности. Однако практически в любом языке программирования можно обнаружить оператор безусловного перехода. Не является исключением и язык Perl. В нем есть три формы этого оператора:

    goto МЕТКА; goto ВЫРАЖЕНИЕ; goto &ПОДПРОГРАММА;

    Первая форма goto МЕТКА передает управление на оператор с меткой МЕТКА, который может быть расположен в любом месте программы, за исключением конструкций, требующих определенных инициирующих действий перед их выполнением. К ним относятся цикл foreach и определение подпрограммы sub.

    Во второй форме оператора безусловного перехода goto ВЫРАЖЕНИЕ возвращаемым значением выражения должен быть метка, на которую и будет передано управление в программе. Эта форма оператора goto является аналогом вычисляемого goto языка FORTRAN:

    @label = ("OUT", "IN");

    Goto $label[l];

    В приведенном фрагменте кода выражение в операторе goto будет вычислено равным строке IN и именно на оператор с этой меткой будет передано управление.

    Последняя форма оператора goto «ПОДПРОГРАММА обладает магическим свойством, как отмечают авторы языка. Она подставляет вызов указанной в операторе подпрограммы для выполняемой в данной момент подпрограммы. Эта процедура осуществляется подпрограммами AUTOLOAD (), которые загружают одну подпрограмму, скрывая затем, что на самом деле сначала была вызвана другая подпрограмма.

    Описание оператора goto приведено нами исключительно для полноты изложения. В программах его следует избегать, так как он делает логику программы более сложной и запутанной. Намного лучше использовать структурированные команды управления потоком вычислений next, last и redo. Если в процессе программирования выяснится, что не обойтись без оператора безусловного перехода, то это будет означать только одно: на этапе проектирования программы она была не достаточно хорошо структурирована. Вернитесь снова к этапу проектирования и постарайтесь реструктурировать ее таким образом, чтобы не требовалось использовать оператор goto.

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

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

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

    Вопросы для самоконтроля

    1. Как определяются простые операторы Perl?

    2. Что такое модификаторы простых операторов и как они влияют на выполнение простых операторов?

    3. Перечислите составные операторы языка Perl.

    4. Что такое блок операторов и что он определяет в программе?

    5. Определите лексическую переменную.

    6. Какой оператор цикла удобнее для перебора всех элементов списка и почему?

    7. Какие команды используются в Perl для управления выполнением циклов?

    8. Как реализуются в Perl переключатели?

    Упражнения

    1. Какие из следующих операторов являются простыми, а какие составными: "abc" if 1; if ($a) { print $a;} do{ $а++; $Ь-;} until $b; while($a eq "а") { $а-;}

    2. Найдите ошибку в программе:

    # peri -w $а = "true"; $b = "false"; if ($a)

    $a = $b; elsif ($b) $b == $a;

    3. Напишите программу, которая по заданному числу STEP печатает лесенку из STEP ступеней (каждая следующая ступень на один символ "-" шире предыдущей):

    I (первая ступень}

    I (вторая ступень)

    I (третья ступень)

    4. Напишите программу, которая во вводимой пользователем строке подсчитывает количество слов, количество не пробельных символов и количество пробельных символов. Словом считать непрерывную последовательность алфавитно-цифровых символов, ограниченных пробельными символами ("\n", "\t", " "). Для завершения программы пользователь должен ввести пустую строку.

    5. Напишите программу, которая читает целую величину ROW и печатает первые ROW строк треугольника Паскаля:


    В этой части речь пойдет об условных операторах и циклах.

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

    Как всегда, начнем сразу с примеров.

    $a = shift ;
    if ($a > 10 ) {
    print "a > 10\n " ;
    }

    Программистам на C-подобных языках эта конструкция должна быть до боли знакома, так что комментировать тут особо нечего. Скажу лишь, что в отличие от Си, опустить фигурные скобки тут нельзя. Точнее говоря, способ есть, но о нем чуть ниже. Конструкции if-else и if-else-if-… на языке Perl выглядят следующим образом:

    $a = shift ;
    if ($a > 10 ) {
    print "a > 10\n " ;
    } else {
    print "a <= 10\n " ;
    }

    if ($a > 0 ) {
    # do something
    } elsif ($a == 0 ) {
    # do something
    } else {
    # do something else
    }

    В общем, все все как мы и ожидаем за одним исключением. Никакого «else if» в Perl нет — вместо этого следует использовать elsif и только его. Elsif может повторяться несколько раз, else использовать не обязательно, фигурные скобки опустить нельзя.

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

    unless ($a == 0 ) {
    # "... если только a не равно нулю"
    ...
    }

    if ($a != 0 ) {
    # то же самое
    # ...
    }

    Unless можно использовать в сочетании с elsif и else, однако никакого «elsunless» в Perl нет.

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


    if ($a > $b ) {
    exit 1 ;
    }


    unless ($b == $c ) {
    exit 2 ;
    }

    # если условие истинное - завершить скрипт с кодом 1
    exit 1 if ($a > $b ) ;
    # если b == c, продолжить выполнение скрипта
    exit 2 unless ($b == $c ) ;

    При этом скобки в последнем примере можно не использовать:

    # если условие истинное - завершить скрипт с кодом 1
    exit 1 if $a > $b ;

    Если вы пишите на Java/PHP или другом Си-подобном языке, такая конструкция скорее всего будет для вас непривычной, но на практике она действительно удобна. В русском языке мы ведь тоже обычно говорим «завершить программу, если …», а не «если …, то …».

    Также, как в C/C++ и PHP, в Perl имеется тернарный оператор?: . Работает он аналогично конструкции if-else, только внутри выражений:

    if ($a > $b ) {
    $a = $a / $b ;
    } else {
    $a = $b / $a ;
    }

    # аналогичный код, использующий оператор "знак вопроса"
    # одна строчка кода вместо пяти
    $a = $a > $b ? $a / $b: $b / $a ;

    Также хотелось бы сказать пару слов об операторах сравнения. Операторы сравнения в языке Perl делятся на две группы — производящие сравнение чисел и сравнение строк.

    Как вы помните, скаляры в Perl можно интерпретировать либо как строки, либо как числа. Например, число 123 больше числа 45, однако строка «123» меньше строки «45». Вот для чего потребовалось несколько групп операторов сравнения. Сравнение строк в Perl производится таким же образом, как и в других современных языках программирования, потому я надеюсь, что тут вопросов не возникает.

    Циклы for, foreach, while/until, do..while/until

    Цикл for прекрасно знаком всем программистам:

    # вывести строку "0 1 2 3 4"
    for ($i = 0 ; $i < 5 ; $i ++ ) {
    print "$i " ;
    }

    В круглых скобках через точку с запятой записывается:

    1. Код, выполняемый перед началом цикла.
    2. Условие, проверяемое перед началом (а не в конце, как думают многие) каждой итерации. Если оно ложно, выполнение цикла завершается.
    3. Код, выполняемый после каждой итерации.

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

    Цикл foreach должен быть хорошо знаком программистам на PHP:

    @arr = (0 , 1 , 2 , 3 , 4 ) ;
    # вывести строку "0 1 2 3 4"
    foreach $i (@arr ) {
    print "$i " ;
    }

    Тело цикла foreach выполняется для каждого элемента массива, указанного в скобках. Важная особенность foreach — в переменную $i не копируется элемент массива @arr, как думают многие . Переменная $i в теле цикла — это и есть сам элемент массива . Таким образом, следующий код увеличивает на единицу значение каждого элемента массива @arr:

    $i = 19880508 ;
    foreach $i (@arr ) {
    $i ++;
    }
    # $i по прежнему равен 19880508

    Также foreach можно использовать для работы с хэшами:

    %hash = (
    aaa => 1 ,
    bbb => 2 ,
    ) ;
    # функция keys возвращает массив, содержащий все ключи хэша
    foreach $k (keys %hash ) {
    print "$k => $hash{$k}\n " ;
    }

    В Perl цикл foreach имеет короткую форму:

    # если Вы забыли, что делает оператор qw,
    # вернитесь к первой части "основ программирования на Perl"
    for $i (qw/1 2 3/ ) {
    print "$i " ;
    }

    То есть фактически везде вместо foreach можно писать просто for. Perl не перепутает такую запись с настоящим циклом for, потому что в последнем нужно писать точки с запятой и так далее.

    Циклы while, until и do работают точно так же, как и в C++ или Pascal/Delphi:

    # выводим "1 2 3 4 5" четырьмя разными способами

    $i = 0 ;
    while ($i < 5 ) { # пока $i меньше пяти
    print ++ $i . " " ;
    }
    print "\n " ; # новая строка

    $i = 0 ;
    until ($i == 5 ) { # пока $i не станет равно пяти
    print ++ $i . " " ;
    }
    print "\n " ;

    $i = 0 ;
    do {
    print ++ $i . " " ;
    } while ($i < 5 ) ; # проверка в конце цикла
    print "\n " ;

    $i = 0 ;
    do {
    print ++ $i . " " ;
    } until ($i == 5 ) ;
    print "\n " ;

    По аналогии с операторами if и unless, существует сокращенная форма записи циклов:

    $i = 0 ;
    print ++ $i . " " while ($i < 5 ) ;
    print "\n " ;

    $i = 0 ;
    print ++ $i . " " until ($i == 5 ) ;
    print "\n " ;

    print "$_ " for (qw/1 2 3 4 5/ ) ; # можно и foreach(qw/1 2 3 4 5/);
    print "\n " ;

    Обратите внимание на последний цикл foreach. Мы ведь помним, что это сокращенная запись foreach, а не цикл for, верно? Последний кстати не имеет короткой записи. Так вот, здесь не было указано имя переменной, с помощью которой мы будем обращаться к элементам массива. В сокращенной записи foreach ее нельзя использовать. В этом случае используется специальная переменная — $_. Следующий пример также вполне рабочий:

    for (qw/1 2 3 4/ ) {
    print "$_" ;
    }

    Его, кстати, можно переписать следующим образом.

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

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

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

    П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 , то правый аргумент не проверяется.
    ||""и && отличаются от подобных операторов в \verb C| тем, что вместо 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 возвращает отрицание аргумента. Оно эквивалентно! , за исключением более низкого приоритета.

    П2.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"