В этой главе речь пойдет об условных операторах и циклах.
Условные операторы
Как всегда, начнем сразу с примеров.
$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 есть возможность уменьшить объем кода, если в случае выполнения условия должна быть выполнена только одна строка кода. Следующие примеры делают одно и то же:
# если условие истинное - завершить скрипт с кодом 1 if($a > $b) { exit 1; } # если b == c, продолжить выполнение скрипта 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.
Оператор | Числовой контекст | Строковой контекст | больше | > | gt | меньше | < | lt | больше или равно | >= | ge | меньше или равно | <= | le | равно | == | eq | неравно | != | ne |
Сравнение строк в 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. Код, выполняемый после каждой итерации. 4. Как и в случае с условными операторами, в циклах опускать фигурные скобки нельзя (для этого также есть специальная форма записи - см ниже).
Цикл 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 "$_"; } Его, кстати, можно переписать следующим образом:
for(1..4) { print "$_"; } Оператор .. (две точки) принимает два операнда и возвращает массив, элементы которого представляют собой все числа от аргумент 1 до аргумент 2 включительно, упорядоченные по возрастанию. Другими словами следующие две строчки делают одно и то же:
@arr1 = 1..4; @arr2 = qw/1 2 3 4/; Также оператор 'две точки' можно использовать со строковыми операндами:
# массив строк - aaa, aab, aac, ..., zzzz @arr1 = "aaa".."zzzz"; Операторы last и next
Операторы last и next в Perl аналогичны операторам break и continue в языке программирования C, только они короче на 1 и 4 символа соответственно. Примеры их использования:
for($i = 0; $i < 10; $i++) { next if $i == 2; # перейти к следующей итерации print "$i "; if($i == 8) { last; } # выйти из цикла } print "\n"; # будет выведено: 0 1 3 4 5 6 7 8 Со вложенными циклами немного сложнее - тут нужно использовать метки:
ATTEMPT: for($i = 1; $i <= 3; $i++) { for($j = 1; $j <= 3; $j++) { if($i == $j and $j == 3) { last ATTEMPT; # выходим из цикла for($i = ... } print "i = $i, j = $j\n"; } } Кстати, метки также используются оператором goto:
goto ATTEMPT; Как Вы, наверное, уже многократно слышали, этот оператор устарел и используя его в своем коде, Вы рискуете быть засмеянными своими коллегами. А в остальном - это вполне нормальный оператор.
Предыдущий урок Следующий урок
8 8 8
| |