Условные операторы Perl
Начнем сразу с примеров.
if($a > 10) {
print «a > 10\n«;
}
В отличие от Си, опустить фигурные скобки тут нельзя. Точнее говоря, способ есть, но о нем чуть ниже. Конструкции 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 делятся на две группы — производящие сравнение чисел и сравнение строк.
Оператор | Сравниваем числа | Сравниваем строки |
больше | > | gt |
меньше | < | lt |
больше или равно | >= | ge |
меньше или равно | <= | le |
равно | == | eq |
неравно | != | ne |
Как вы помните, скаляры в Perl можно интерпретировать либо как строки, либо как числа. Например, число 123 больше числа 45, однако строка «123» меньше строки «45». Вот для чего потребовалось несколько групп операторов сравнения. Сравнение строк в 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«;
}
}