Изучаем Perl, часть 3
Автор: © Бен Окопник [Ben Okopnik]
|
Когда говорят, что Perl хорош для "склеивания" других программ
в единое целое [glue language], в действительности имеют в виду то, что Perl
хорошо подходит для того, чтобы приводить все в порядок после ошибок других
программ. Обзор В статье этого месяца мы рассмотрим условные операторы и операторы цикла, используемые
в Perl, и разберем несколько скриптов, в которых они используются. Мы также
выясним, как эти операторы работают с переменными Perl и бросим беглый взгляд
на обработку пользовательского ввода. Коль скоро вы начнете понимать этот раздел,
я рекомендовал бы вам "хакнуть" парочку пробных скриптов, причем
наиграться с ними как следует. Понятно, что у вас будут ошибки, но начиная с
этого момента вам действительно необходимо дополнить чтение первыми самостоятельными
шагами, пусть и вволю нападавшись и вывалявшись в грязи. Кто не играет, тот
не пьет шампанское... Условные операторы Вот условные операторы, применяемые в Perl; если вы привыкли к условным операторам в других языках, то не встретите ничего необычного. Perl проверяет истинность или ложность условия и на основании этой проверки передает управление той или иной ветви.
if ( traffic_light_is_red ) { # Если светофор красный, то stop; # Действие 1 -- остановка } elsif ( traffic_light_is_yellow ) { # Если же он желтый, то hit_the_gas; # Действие 2 -- подгазовываем } else { # Во всех остальных случаях proceed_with_caution; # Действие 3 -- осторожно движемся вперед } Обратите внимание, что оператор "elseif" -- необязателен, равно как и "else". Также обратите внимание, что "else" служит ловушкой для "всех остальных вариантов": если цвет светофора не желтый и не красный -- перегорел ли он, повален в результате аварии или что-либо еще -- мы 'осторожно движемся вперед'. В отличие от C, даже один оператор должен быть оформлен в виде блока (заключен в фигурные скобки): if ( $tomato eq "красный" ) print "Созрел.\n";
# НЕВЕРНО!
unless ( $blarg == $foo ) {
# Если условие 1 не выполняется Вполне очевидно. Полезно представить "unless", как условный оператор
"if not". Повторяюсь, "else" -- не обязательная часть оператора.
Нет, такой штуки, как "elseunless" не бывает.:) Циклы О, удивительные циклы. Это такие штуки, которые заставляют действия выполняться
столько раз, сколько вы хотите, в зависимости от установленного условия. Вы
можете даже сказать, что циклы -- основная причина, по которой компьтеры используются
в их главной роли: инструментов для аккуратного выполнения одной и той же работы
много раз подряд. Вот три вида операторов цикла, наиболее обычных в Perl:
while ( $кошка eq "гуляет" ) { # До тех пор, пока условие 1 верно print "Мыши играют.\n"; # Выполняем действие 1 }
until ( $time > 1159 ) { # До тех пор, пока условие 1 не выполняется print "Еще утро.\n" # Выполняем действие 1 }
Цикл "for" реализуется двумя разными способами. Первый -- как оператор "for" в C: for ( $n = 99; $n > 0; $n-- ) {
В этом случае мы устанавливаем начальное значение $n (99), уменьшаем его на единицу при каждом проходе цикла и проверяем, что оно больше 0. Если нет, то выходим из цикла. Второй способ, напоминающий оператор "foreach" в Clipper, FoxPro и других подобных языках, встречается намного чаще: foreach $n ( 0..1000 ) {
То же самое можно сделать и так: for ( 0..1000 ) { Примечание переводчика: модификация программы таким образом, чтобы слово "бананов" выводилсь в правильном падеже, оставляется читателю в качестве самостоятельного упражнения. :) Наш старый знакомый "$_" (объяснение дается в предыдущей статье) Действительно удобно. Обратите внимание, что "foreach" -- это просто другая форма для "for" и что эти формы можно использовать одну вместо другой.
Все описанные выше условные операторы и операторы цикла могут использоваться и как модификаторы отдельных выражений: print "Это строка $_ из 50.\n" for ( 1..50 ); Приведенный код напечатает 50 строк, пронумеровав их очевидным образом. print "Нашел!" if /Waldo/; А этот напечатает строку "Нашел!", если в буфере по умолчанию ($_)
содержится совпадение образцу "Waldo". Интересным является хорошо сочетающийся с циклами и условными операторами факт, что в Perl пустые переменные возвращают значение "null", которое интерпретируется, как "false". Это просто идеально для выявления таких переменных: print if $_; # Напечатает $_ если там что-нибудь есть Следующий пример показывает, что нулевые значения тоже расцениваются, как ложь: print "5280 -- истина.\n" if 5280; # Вывод состоится. print "0 -- истина.\n" if 0; # Вывод не состоится. А вот пример с использованием списка: while ( @a ) {
Когда последний элемент будет изъят, цикл завершится. unless ( %hash ) {
Если "%hash" пуст, заполним его начальными значениями. Оператор диапазона [range], который мы уже пару раз пользовали -- очень полезная штуковина: он позволяет нам указать диапазон чисел или символов. Обратите внимание, что диапазоны должны быть определенного "вида" -- если указать ('a'..'Z') или ('A'..'z'), то выйдет не то, что вы ждете. И еще, нельзя указать диапазон ('z'..'a'), такой оператор также не сработает. Существует, однако, простой способ сделать тоже самое: foreach $letter ( reverse 'a'..'z' ) {
Зато "буквенные списки" будут формироваться правильно: for ( 'aa'..'zz' ) {
Пользовательский ввод Получение клавиатурного ввода, да и вообще данных из STDIN -- например строк, перенаправленных нашему скрипту в качестве входных данных в конструкции, наподобие следующей cat file | perl_script -- это просто; именно для этого и создан "бубновый" оператор
Perl'а. while ( <> ) { # Захватывается
все, введенное с клавиатуры или перенаправленный ввод Приведенный код будет работать в точности, как команда "cat" -- напечатает весь направленный ему ввод, выведет на терминал содержимое переданного в качестве аргумента файла и будет принимать (и повторять на экране) введенные пользователем строки до тех пор, пока не будут нажаты Ctrl-D или Ctrl-C. То же самое можно написать и так: print while <>; для более "Перлового" вида. Обратите внимание, что "<>" и <STDIN> похожи, но не эквивалентны: print while <STDIN>; будет откликаться на клавиатурный и перенаправленный ввод, но не будет выводить содержимого переданного как аргумент файла. Мне не доводилось сталкиваться с ситуацией, в которой потребовалось бы такое поведение, поэтому я просто использую "<>". Если вы хотите сохранить введенные пользователем данные в переменной, то и с этим Perl легко справляется -- но здесь имеется "капкан", о котором вам следует знать: $answer = <>; # Получаем
ввод и сохраняем его в переменной Данный скрипт всегда будет выводить "Непонятка!". Хм... но выглядит то это верным, в чем же проблема? Проблема в том, что Perl считывает все, что вы вводите. Итак, какую клавишу вы нажиматет после "y"? "Enter"! Так что переменная $answer содержит НЕ "y", а "y\n" -- ответ и символ перевода строки! И что же делать? Ну конечно же в Perl есть функция, которую всегда следут использовать при получении введенных пользователем данных: chomp ( $answer = <> ); "chomp" удалит символ новой строки (или символ "конца строки") из
последовательности символов, к которому вы его применили. Он также удалит все
EOL'ы из массива строк, полученного в качестве аргумента. Старая функция "chop"
из Perl 4 удаляла последний символ из полученного скаляра (или элемента массива)
не зависимо от того, что это за символ. Эта функция по-прежнему доступна на
тот случай, если вам потребуется именно это, но для обработки пользовательского
ввода лучше пользоваться функцией "chomp" (по выдаваемых Perl'ом сообщениях
об ошибках она известна как "safe chop"). Упражнения для ума В порядке самообразования и развлечения попробуйте написать пару скриптов: Скрипт, получающий число на входе и печатающий "Привет!" соответствующее число раз. В качестве приза можете проверять ввод на неверные (не числовый) символы (подсказка: воспользуйтесь оператором поиска по образцу //). Скрипт, который получив ответ на вопрос "Который час?" (в виде числа от 0 до 23) выдает в стандартный поток вывода, к примеру, "Good morning", "Dobriy den'", "Guten Abend", or "Buenas noches". Если у вас выйдет что-либо особо умное, не колеблясь присылайте мне для следующей статьи -- получите зачет, раз, я с удовольствием препарирую ваше творение, это два, и, наконец, мы оба обретем широкую известность в узких кругах и в результате сможем позволить себе поселиться на Белизе после выхода на пенсию. Не забудьте: ваша "shebang line" всегда должна содержать "-w". Если
не просить Perl помогать в случае ошибок -- потеряете много времени. Пусть трудится
компьютер! #!/usr/bin/perl -w
Бен Окопник [Ben Okopnik] Ссылки: Страницы Perl man по теме (имеются в каждой pro-Perl-y сконфигурированной
системе:) perl - overview
perlfaq - Perl FAQ
"perldoc", "perldoc -q" and "perldoc -f"
|
Copyright © 2001, Ben Okopnik. Copying license http://www.linuxgazette.com/copying.html Published in Issue 65 of Linux Gazette, April 2001 |
Вернуться на главную страницу |