Быстрый старт в Perl. Изучаем Perl

Известный как "книга с ламой", этот учебник, впервые изданный в 1993 году, выходит уже пятым изданием, в котором описываются последние изменения в языке вплоть до версии Perl 5.10.

В пятое издание вошли такие темы, как типы данных и переменные Perl, пользовательские функции, операции с файлами, регулярные выражения, операции со строками, списки и сортировка, управление процессами, умные сравнения, модули сторонних разработчиков и другие.

Perl - язык для тех, кто хочет быстро и эффективно выполнять свою работу. Некогда создававшийся как инструмент для сложной обработки текстов, предназначенный для системных администраторов, сейчас Perl является полнофункциональным языком программирования, подходящим для решения практически любых задач на почти любой платформе - от коротких служебных программ, умещающихся в командной строке, до задач веб-программирования, исследований в области биоинформатики, финансовых расчетов и многого другого.

Иные книги учат вас программировать на Perl, в то время как книга "Изучаем Perl" сделает из вас Perl-программиста.

Отзывы читателей

"Я вообще-то очень привередлив к качеству учебников, часто на них ругаюсь. Но эта книга просто гениальна. Отличный учебник, как для новичков в программировании, так и для опытных программистов, не знакомых с Перлом. Подача материала - выше всяких похвал. Я бы оценил эту книгу даже выше, чем "тот самый лама-бук", т. к. писать кратко и просто - особенно сложно."

Посетитель сайта ozon.ru

"Лет 5 назад я купил предыдущее издание этой книги и начал программировать на Perl. С тех пор это стало и моей профессией, и любимым хобби:) Когда меня спрашивают, как изучить perl - я рекомендую эту книгу."

Рэндал Л. Шварц- ветеран программирования с 20-летним стажем. Является специалистом в области архитектуры программного обеспечения, системного администрирования, безопасности, составления технической документации и обучения. Рэндал участвовал в написании ряда общепризнанных книг: "Programming Perl", "Learning Perl", "Learning Perl for Win32 Systems" и "Effective Perl Learning", а также вел постоянные рубрики в журналах "WebTechniques", "Performance Computing", "SysAdmin" и "Linux Magazine". Постоянно участвует в работе новостных групп Perl, модерирует группу comp.lang.perl.announce с момента ее появления. О его искрометном юморе и техническом мастерстве ходят легенды (вероятно, некоторые из них сочинил он сам). Желание Рэндала вносить свой вклад в сообщество Perl вдохновило его на создание и начальное финансирование "Института Perl". Рэндал также является одним из учредителей и членов правления Perl Mongers (perl.org), всемирного народного движения за распространение Perl. С 1985 года Рэндал является владельцем и руководителем фирмы Stonenenge Consulting Services, Inc. С ним можно связаться по адресу [email protected]; он охотно беседует о Perl и на другие связанные темы.

Том Феникс- работает в области образования с 1982 года. После 13 лет вскрытий, взрывов, работы с интересными животными и высоковольтными разрядами в научном музее он начал вести уроки Perl в Stonehenge Consulting Services, где работает с 1996 года. С тех пор он побывал во многих интересных местах, так что вполне возможно, что вы скоро встретитесь с ним на собрании Perl Mongers. В свободное время отвечает на вопросы в группах Usenet comp.lang.perl.misc и comp.lang.perl.moderated, а также вносит свой вклад в разработку Perl. Помимо программирования на Perl, общения с Perl-хакерами и прочим, Том увлекается любительской криптографией и говорит на эсперанто. Живет в Портленде, штат Орегон.

Брайан Д. Фой - работал инструктором в Stonehenge Consulting Services с 1998 года; работает на Perl со времени обучения в аспирантуре в области физики, несгибаемый пользователь Mac с момента появления своего первого компьютера. Основал первую группу пользователей Perl (New York Perl Mongers), а также некоммерческую организацию Perl Mongers, Inc., которая помогла сформировать свыше 200 групп пользователей Perl по всему миру. Занимается сопровождением раздела perlfaq в основной документации Perl, нескольких модулей из CPAN и ряда автономных сценариев. Издает "The Perl Review" - журнал, посвященный Perl, и часто выступает с докладами на конференциях. Его материалы о Perl появляются в O\"Reilly Network, "The Perl Journal", "Dr. Dobbs" и "The Perl Review", в группе use.perl.org и в нескольких группах Usenet, посвященных Perl.

Проблема обучения Perl"у, как первому языку программирования, состоит в том, что обучающиеся не могут его оценить до тех пор, пока не начнут изучать второй язык. Проблема обучения Perl"у, как второму языку состоит в том, что ни один язык программирования, взятый в отдельности, не годится на роль предшественника.
-- Ларри Уолл

Когда говорят, что Perl хорош для "склеивания" других программ в единое целое , в действительности имеют в виду то, что Perl хорошо подходит для того, чтобы приводить все в порядок после ошибок других программ.
-- из высказывания Марка-Джейсона Доминуса в comp.lang.perl.misc

Обзор

В статье этого месяца мы рассмотрим условные операторы и операторы цикла, используемые в 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"; # НЕВЕРНО!
if ($tomato eq "красный") { print "Созрел.\n"; } # Правильно

unless ($blarg == $foo) { # Если условие 1 не выполняется
print "Не равны!.\n"; # Действие 1
}
else { # В противном случае
print "Они равны.\n"; # Действие 2
}

Вполне очевидно. Полезно представить "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--) {
print "$n бутылок пива в ряд, $n бутылок пива,";
...
}

В этом случае мы устанавливаем начальное значение $n (99), уменьшаем его на единицу при каждом проходе цикла и проверяем, что оно больше 0. Если нет, то выходим из цикла.

Второй способ, напоминающий оператор "foreach" в Clipper, FoxPro и других подобных языках, встречается намного чаще:

foreach $n (0..1000) {
print "День $n на пустынном острове. К этому моменту я съел ";
print $n * 100, " бананов. Надеюсь, меня скоро спасут.\n";
...
}

То же самое можно сделать и так:

for (0..1000) {
print "День $_ на пустынном острове. К этому моменту я съел ";
print $_ * 100, " бананов. Надеюсь, меня скоро спасут.\n";
...
}

Примечание переводчика : модификация программы таким образом, чтобы слово "бананов" выводилсь в правильном падеже, оставляется читателю в качестве самостоятельного упражнения. :)

Наш старый знакомый "$_" (объяснение дается в предыдущей статье) Действительно удобно. Обратите внимание, что "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) {
print pop @a; # "Выбрать" последнее значение из @a и напечатать его
$count = @a; # Получить число элементов в @a
print $count, " элементов осталось в \@a.\n";
}

Когда последний элемент будет изъят, цикл завершится.

unless (%hash) {
%hash = ("first" => "Mighty Joe",
"last" => "Young",
"type" => "gorilla",
"from" => "Pangani Mountains",
"born" => "1949",
"Mom" => "Jill",
"Dad" => "Gregg"
);
}

Если "%hash" пуст, заполним его начальными значениями.

Оператор диапазона , который мы уже пару раз пользовали -- очень полезная штуковина: он позволяет нам указать диапазон чисел или символов. Обратите внимание, что диапазоны должны быть определенного "вида" -- если указать ("a".."Z") или ("A".."z"), то выйдет не то, что вы ждете. И еще, нельзя указать диапазон ("z".."a"), такой оператор также не сработает. Существует, однако, простой способ сделать тоже самое:

foreach $letter (reverse "a".."z") {
print "$letter\n";
}

Зато "буквенные списки" будут формироваться правильно:

for ("aa".."zz") {
print "$_ "; # Напечатает "aa ab ac ... zx zy zz"
}

Пользовательский ввод

Получение клавиатурного ввода, да и вообще данных из STDIN -- например строк, перенаправленных нашему скрипту в качестве входных данных в конструкции, наподобие следующей

cat file | perl_script

Это просто; именно для этого и создан "бубновый" оператор Perl"а.

while (<>) { # Захватывается все, введенное с клавиатуры или перенаправленный ввод
print; # Будет печатать каждую введенную строку до тех пор, пока они не закончатся
}

Приведенный код будет работать в точности, как команда "cat" -- напечатает весь направленный ему ввод, выведет на терминал содержимое переданного в качестве аргумента файла и будет принимать (и повторять на экране) введенные пользователем строки до тех пор, пока не будут нажаты Ctrl-D или Ctrl-C. То же самое можно написать и так:

print while <>;

для более "Перлового" вида. Обратите внимание, что "<>" и похожи, но не эквивалентны:

print while ;

будет откликаться на клавиатурный и перенаправленный ввод, но не будет выводить содержимого переданного как аргумент файла. Мне не доводилось сталкиваться с ситуацией, в которой потребовалось бы такое поведение, поэтому я просто использую "<>".

$answer = <>; # Получаем ввод и сохраняем его в переменной
if ($answer eq "y") {
print "Да\n";
}
elsif ($answer eq "n") {
print "Нет\n";
}
else {
print "Непонятка!\n";
}

Данный скрипт всегда будет выводить "Непонятка!". Хм... но выглядит то это верным, в чем же проблема?

Проблема в том, что 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
print "До скорого!"

Бен Окопник
perl -we"print reverse split//,"rekcah lreP rehtona tsuJ""
Ссылки:

Страницы Perl man по теме (имеются в каждой pro-Perl-y сконфигурированной системе:)

perl - overview perlfaq - Perl FAQ
perltoc - doc TOC perldata - data structures
perlsyn - syntax perlop - operators/precedence
perlrun - execution perlfunc - builtin functions
perltrap - traps for the unwary perlstyle - style guide

"perldoc", "perldoc -q" and "perldoc -f"

Если программа должным образом работает при вызове ее из командной строки, необходимо инсталлировать ее на компьютере-сервере. Приемлемые места размещения зависят от сервера, хотя для CGI-сценариев часто исполь-зуется каталог

/usr/etc/httpd/cgi-bin/ и его подкаталоги. Обсудите зтот вопрос с Web-мастером или системным администратором.

После завершення инсталляции вашей программы в CGI-каталоге ее можно выполнять, указывая броузеру ее путевое имя в составе

URL. Напри-мер, если ваша программа называется howdy, URL будет выглядеть так:

http://vww.SOMEWHERE.org/cgi-bin/howdy.

Сервери обычно позволяют использовать вместо ддинных путевых имен псевдонимы. Сервер, имеющий адрес

www.SOMEWHERE.org, может запросто перевести cgi-bin/howdy, содержащийся в зтом URL, в нечто вроде usr/etc/httpd/ cgi-bin/howdy. Ваш системний администратор или Web-мастер может подска-зать, какой псевдоним следует использовать при обращении к вашей программе. Зтот заголовок необходим для протокола HTTP, о котором мы упоминали выше.

Передача параметров через

CGI

Для передачи параметров в CGI-программы (точнее, в большинство CGI-программ) никакие формы не нужны. Чтобы убедиться в этом, замените

URL на http://www.SOMEWHERE.org/cgi-bin/ice_creain?flavor=mint.

Когда вы "нацеливаете" свой броузер на этот

URL, броузер не только просит Web-сервер вызвать программу ice_cream, но и передает в нее строку flavor=mint. Теперь дело программы - прочитать данную строку-аргумент и разобрать ее. Эта задача не так проста, как кажется. Многие программы пытаются решить ее и разобрать запрос самостоятельно, но большинство "самодельных" алгоритмов время от времени отказывают. Учитывая то, насколько сложно найти правильное решение такой задачи для всех возможных случаев, вам, наверное, не следует писать код самим, особенно при наличии отличных готовых модулей, которые выполняют этот хитрый синтаксический анализ за вас.

К вашим услугам

- модуль CGI.pm, который всегда разбирает входящий CGI-запрос правильно. Чтобы вставить этот модуль в свою программу, просто напишите

где-нибудь в начале программы*.

Оператор

use похож на оператор # include языка С тем, что в процессе компиляции извлекает код из другого файла. Но он допускает также использование необязательных аргументов, показывающих, к каким функциям и переменным из этого модуля вы хотели бы обращаться. Поместите их в список, следующий за именем модуля в операторе use,- и вы сможете обращаться к указанным функциям и переменным так, как будто они ваши собственные.

В данном случае все, что нам нужно использовать из модуля

CGI.pm - это функция param () **.

Если аргументы не указаны, функция

param () возвращает список всех полей, имевшихся в HTML-форме, на которую отвечает данный CGI-сце-нарий. (В текущем примере это поле flavor, а в общем случае - список всех имен, содержащихся в строках имя=значение переданной формы.) Если указан аргумент, обозначающий поле, то param () возвращает значение (или значения), связанные с этим полем. Следовательно, param (" flavor") возвращает "mint", потому что в конце URL мы передали ?flavor=mint. Имена всех Perl-модулей имеют расширение рт. Более того, оператор use подразумевает это расширение. О том, как создавать свои собственные модули, вы можете узнать в главе 5 книги Programming Perl или на man-странице perlmod(l). Некоторые модули автоматически экспортируют все свои функции, но, поскольку CGI.pm - это на самом деле объектный модуль, замаскированный под обычный, мы должны запрашивать его функции явно.

Несмотря на то что в нашем списке для оператора

use имеется всего один элемент, мы будем использовать запись qw (). Благодаря этому нам будет легче впоследствии раскрыть этот список.

#!/usr/local/bin/perlS -w

# программа ответа на форму о любимом сорте мороженого (версия

1) use CGI qw(param);

print “END_of_Start;

Content-type: text/html

Hello World

Greetings, Terrans! END_of_Start

print "

Your favorite flavor is $favorite. print “All_Done;

All Done

Как сократить объем вводимого текста

Вводить все равно приходится очень много, но в

CGI.pm есть множество удобных функций, упрощающих набор. Каждая из этих функций возвращает строковое значение, которое вы будете выводить. Например, header () возвращает строковое значение, содержащее строку Content-type с последующей пустой строкой, start_html (строка ) возвращает указанную строку как HTML-титул (название документа), hi (строка) возвращает указанную строку как HTML-заголовок первого уровня, а р (строка) возвращает указанную строку как новый HTML-абзац.

Мы могли бы перечислить все эти функции в списке, прилагаемом к оператору

use, но такой список разросся бы до небывалых размеров. В CGI.pm, как и во многих других модулях, имеются так называемые директивы импорта - метки, которые обозначают группы импортируемых функций. Вам нужно лишь поставить желаемые директивы (каждая из которых начинается двоеточием) в начале своего списка импорта. В модуле CGI.pm имеются такие директивы:

Импортировать все методы обработки аргументов, например

param ().

Импортировать все методы создания заполняемых форм, например

text-field().

Импортировать все методы, которые генерируют стандартные элементы

HTML 2.0.

Импортировать все методы, которые генерируют элементы, предложенные в

HTML 3.0 (такие как , и ).

Импортировать все методы, которые генерируют расширения

HTML, характерные для Netscape.

Импортировать все сокращения, генерируемые

HTML (т.е. "html2" + "html3" + "netscape").

Импортировать "стандартные" возможности:

"html2", "form" и "cgi".

Импортировать все имеющиеся методы. Полный список приведен в модуле

CGI.pm, где определяется переменная %tags.

Мы будем использовать только директиву

: standard. (Подробная информация об импортировании функций и переменных из модулей приведена в главе 7 книги Programming Perl, а также на man-странице Exporter 3).}

Вот как выглядит наша программа со всеми сокращениями, которые используются в

CGI.pm:

#!/usr/local/bin/perlS -w

# cgi-bin/ice_cream #

программа ответа на форму о любимом сорте мороженого (версия 2) use CGI qw(:standard);

print header() ;

print start_html("Hello World"), hi ("Hello World");

my $favorite = param("flavor");

print p("Your favorite flavor is $favorite.");

print end_html();

Видите, насколько это проще? Вам не нужно беспокоиться о декодировании данных формы, о заголовках и HTML-тексте, если вы этого не хотите.

Генерирование формы

Если вам надоело вводить параметры своей программы в броузер

- создайте заполняемую форму. К таким формам привыкли большинство пользователей. Компоненты формы, которые принимают вводимые пользователем данные, иногда называются vidgets; считается, что этот термин гораздо удобнее, чем "устройства графического ввода". Такие компоненты форм включают одно- и многостроковые текстовые поля, всплывающие меню, прокручиваемые списки, различные виды кнопок и отмечаемых блоков.

Создайте следующую HTML-страницу, которая включает форму с одним компонентом "текстовое поле" и кнопкой передачи. Когда пользователь щелкает на кнопке передачи*, вызывается сценарий

ice_cream, заданный атрибутом ACTION.