Глава 6.5. Операторы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 = <STDIN>; ... } 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 выполняется следующим образом:
Следующий пример выводит на экран числа от одного до десяти: $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 выполняется следующим образом:
Следующий пример выводит на экран числа от одного до десяти: $i = 1; until ($i > 10) { print "$i\n" } continue { $i++ } 6.5.2.5. Оператор цикла forОператор цикла for имеет вид: for (инициализация; условие; изменение) БЛОК Оператор for выполняется следующим образом:
Данный оператор обычно используется в тех случаях, когда количество повторений цикла известно заранее. Так, мы могли бы записать предыдущий пример короче: for ($i = 1; $i <= 10; $i++) { print "$i\n" } 6.5.2.6. Оператор итерации foreachОператор foreach выполняет заданные действия для каждого элемента списка или массива. Он имеет две формы: foreach переменная (список) БЛОК foreach переменная (список) БЛОК continue БЛОК1 Оператор foreach выполняется следующим образом:
Приведем все тот же пример с печатью чисел от 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 (<STDIN>) { last LINE if /^$/; # прервать цикл, если встретилась пустая строка ... } 6.5.2.9. Оператор nextОператор next начинает новую итерацию указанного цикла. Он имеет две формы: next метка next Первая форма оператора начинает новую итерацию цикла с заданной меткой. Вторая форма начинает новую итерацию самого внутреннего из выполняющихся в данный момент вложенных циклов. Если цикл имеет блок continue, то он будет выполнен перед началом новой итерации. Пример: LINE: while (<STDIN>) { next LINE if /^#/; # пропускать комментарии ... } 6.5.2.10. Оператор redoОператор redo начинает новую итерацию указанного цикла без проверки условия его выполнения. Он имеет две формы: redo метка redo Первая форма оператора начинает новую итерацию цикла с заданной меткой. Вторая форма начинает новую итерацию самого внутреннего из выполняющихся в данный момент вложенных циклов. Если цикл имеет блок continue, то он не выполняется. Следующий пример удаляет комментарии из программы на языке Pascal, где они имеют вид { } (пример упрощен, т. к. не учитывает, что символы {} могут содержаться в строковых константах): LINE: while (<STDIN>) { while (s|({.*}.*){.*}|$1 |) {} s|{.*}| |; if (s|{.*| |) { $front = $_; while (<STDIN>) { 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. Оператор перехода gotoPERL содержит оператор перехода goto трех видов: goto метка goto выражение goto &имя Первая форма оператора передает управление оператору с указанной меткой. Управление не может быть передано внутрь конструкции, требующей инициализации, например, внутрь подпрограммы или оператора foreach. Вторая форма это "вычисляемый goto": он вычисляет значение выражения и передает управление на полученную в результате метку, например: goto ("LABEL1", "LABEL2", "LABEL3")[$i]; Третья форма это вообще не goto в обычном смысле слова. Этот оператор подставляет вызов подпрограммы имя вместо выполняющейся сейчас подпрограммы. Она используется подпрограммами AUTOLOAD(), которые хотят незаметно подменить вызов одной подпрограммы другой. Имя не обязано быть именем подпрограммы; это может быть скалярная переменная или блок, значением которых является ссылка на подпрограмму. Правила хорошего тона рекомендуют не пользоваться оператором перехода. Для языка PERL это справедливо вдвойне, поскольку остальные его операторы обеспечивают очень гибкое управление ходом выполнения программы. | ||||||||||||