Основы Perl — условные операторы и циклы
Ну вот дошли руки написать продолжение к посту Основы программирования на Perl. В этой части речь пойдет об условных операторах и циклах.
Условные операторы
Как всегда, начнем сразу с примеров.
if($a > 10) {
print "a > 10\n";
}
Программистам на C-подобных языках эта конструкция должна быть до боли знакома, так что комментировать тут особо нечего. Скажу лишь, что в отличии от си, опустить фигурные скобки тут нельзя. Точнее говоря, способ есть, но о нем чуть ниже. Конструкции if-else и if-else-if-… на языке Perl выглядят следующим образом:
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. Следующие два куска кода делают одно и то же:
# '... если только a не равно нулю'
...
}
# то же самое
# ...
}
Unless можно использовать в сочетании с elsif и else, однако никакого «elsunless» в Perl нет.
В Perl есть возможность уменьшить объем кода, если в случае выполнения условия должна быть выполнена только одна строка кода. Следующие примеры делают одно и то же:
if($a > $b) {
exit 1;
}
# если b == c, продолжить выполнение скрипта
unless($b == $c) {
exit 2;
}
exit 1 if($a > $b);
# если b == c, продолжить выполнение скрипта
exit 2 unless($b == $c);
При этом скобки в последнем примере можно не использовать:
exit 1 if $a > $b;
Если вы пишите на Java/PHP или другом си-подобном языке, такая конструкция скорее всего будет для вас непривычной, но на практике она действительно удобна. В русском языке мы ведь тоже обычно говорим «завершить программу, если …», а не «если …, то …».
Также, как в C/C++ и PHP, в Perl имеется условных оператор ?. Работает он аналогично конструкции if-else, только внутри выражений:
$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 прекрасно знаком всем программистам:
for($i = 0; $i < 5; $i++) {
print "$i ";
}
В круглых скобках через точку с запятой записывается:
- Код, выполняемый перед началом цикла.
- Условие, проверяемое перед началом (а не в конце, как думают многие) каждой итерации. Если оно ложно, выполнение цикла завершается.
- Код, выполняемый после каждой итерации.
Как и в случае с условными операторами, в циклах опускать фигурные скобки нельзя (для этого также есть специальная форма записи — см ниже).
Цикл foreach должен быть хорошо знаком программистам на PHP:
# вывести строку '0 1 2 3 4'
foreach $i (@arr) {
print "$i ";
}
Тело цикла foreach выполняется для каждого элемента массива, указанного в скобках. Важная особенность foreach — в переменную $i не копируется элемент массива @arr, как думают многие. Переменная $i в теле цикла — это и есть сам элемент массива. Таким образом, следующий код увеличивает на единицу значение каждого элемента массива @arr:
foreach $i (@arr) {
$i++;
}
# $i по прежнему равен 19880508
Также foreach можно использовать для работы с хэшами:
aaa => 1,
bbb => 2,
);
# функция keys возвращает массив, содержащий все ключи хэша
foreach $k (keys %hash) {
print "$k => $hash{$k}\n";
}
В Perl цикл foreach имеет короткую форму:
# вернитесь к первой части "основ программирования на Perl"
for $i (qw/1 2 3/) {
print "$i ";
}
То есть фактически везде вместо foreach можно писать просто for. Perl не перепутает такую запись с настоящим циклом for, потому что в последнем нужно писать точки с запятой и так далее.
Циклы while, until и do работают точно так же, как и в C++ или Pascal/Delphi:
$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, существует сокращенная форма записи циклов:
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 ее нельзя использовать. В этом случае используется специальная переменная — $_. Следующий пример также вполне рабочий:
print "$_";
}
Его, кстати, можно переписать следующим образом:
print "$_";
}
Оператор .. (две точки) принимает два операнда и возвращает массив, элементы которого представляют собой все числа от аргумент 1 до аргумент 2 включительно, упорядоченные по возрастанию. Другими словами следующие две строчки делают одно и то же:
@arr2 = qw/1 2 3 4/;
Также оператор «две точки» можно использовать со строковыми операндами:
@arr1 = "aaa".."zzzz";
Операторы last и next
Операторы last и next в Perl аналогичны операторам break и continue в языке программирования C, только они короче на 1 и 4 символа соответственно. Примеры их использования:
next if $i == 2; # перейти к следующей итерации
print "$i ";
if($i == 8) { last; } # выйти из цикла
}
print "\n";
# будет выведено: 0 1 3 4 5 6 7 8
Со вложенными циклами немного сложнее — тут нужно использовать метки:
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:
Как вы, наверное, уже многократно слышали, этот оператор устарел и используя его в своем коде, вы рискуете быть засмеянными своими коллегами. А в остальном — это вполне нормальный оператор.
Думаю, на сегодня это все. Если у вас есть вопросы по языку Perl (любые — не только по теме поста), смело задавайте их в комментариях. Чтобы не пропустить новые посты, посвященные основам программирования на Perl, подпишитесь на обновления блога.
Дополнение: Очень познавательная статья про операторы диапазона опубликована на HabraHabr.
Далее: Директива use strict, ссылки и функции