Деструкторы
Деструкторы
В главе 9 было сказано, что для каждого субъекта ссылки поддерживается счетчик ссылок. Область памяти, занимаемая субъектом ссылки, освобождается,, когда значение счетчика ссылок становится равным нулю. Объект, как мы знаем, является просто ссылкой, поэтому с ним происходит то же самое: когда значение счетчика ссылок становится равным нулю, внутренняя структура данных, представляющая объект (обычно хеш-массив), освобождает память. Интерпретатор сам отслеживает значение счетчика ссылок и автоматически удаляет объект. Пользователь может определить собственные действия, завершающие работу объекта, при помощи специального метода — деструктора. Деструктор нужен для того, чтобы корректно завершить жизненный цикл объекта, например, закрыть открытые объектом файлы или просто вывести нужное сообщение. В соответствующее время деструктор будет автоматически вызван интерпретатором.
Деструктор должен быть определен внутри своего класса. Он всегда имеет имя DESTROY, а в качестве единственного аргумента — ссылку на объект, подлежащий удалению. Создавая подпрограмму-деструктор, следует обратить внимание на то, чтобы значение ссылки на удаляемый объект, передаваемое в качестве первого элемента массива параметров $_[0], не изменялось внутри подпрограммы.
Подчеркнем, что создавать деструктор не обязательно. Он лишь предоставляет возможность выполнить некоторые дополнительные завершающие действия. Основная работа по удалению объекта выполняется автоматически. Все объекты-ссылки, содержащиеся внутри удаляемого объекта как его данные, также удаляются автоматически.
Метод DESTROY не вызывает другие деструкторы автоматически. Рассмотрим следующую ситуацию. Конструктор класса, вызывая конструктор своего базового класса, создает объект базового класса. Затем при помощи функции bless о делает последний объектом собственного класса. Оба класса, текущий и базовый, имеют собственные деструкторы. Поскольку конструктор базового класса, вызванный конструктором текущего класса, создал собственный объект, то при его удалении должен вызываться деструктор базового класса. Но этот объект уже перестал быть объектом базового класса, так как одновременно объект может принадлежать только одному классу. Поэтому при его удалении будет вызван только деструктор текущего класса. При необходимости деструктор текущего класса должен вызвать деструктор своего базового класса самостоятельно.
Классы и объекты
Классы и объекты
Эта глава не предназначена для того, чтобы изучать по ней основы объектно-ориентированного программирования (ООП). Мы лишь хотим дать представление о том, как основные идеи ООП реализованы в языке Perl. Начнем с краткого обзора этих идей. В основе ООП лежат понятия класса и объекта. Эти понятия тесно связаны друг с другом.
Класс представляет собой сочетание структуры данных и тех действий, которые можно выполнить над этими данными. Данные называют свойствами, а действия — методами. Совмещение в классе структуры данных и действий над ними называют инкапсуляцией.
Объект является экземпляром класса. Свойства объекта обусловлены его принадлежностью к определенному классу. Понятия "объект" и "класс" отражают два различных вида иерархий, которые можно обнаружить в любой достаточно сложной системе. Рассмотрим пример.
Персональный компьютер является сложной системой. Жесткий диск — составная часть этой системы. Другими ее частями являются центральный процессор, память и т. д. Можно сказать, что жесткий диск — это часть структурной иерархии под названием "персональный компьютер". С другой стороны, жесткий диск является абстракцией, обобщением свойств, присущих всем жестким дискам, и этим он отличается, например, от гибкого диска, рассматриваемого как абстракция, обобщающая свойства всех гибких дисков. В типовой иерархии жесткие диски Quantum — это особый тип жестких дисков, жесткие диски Quantum Fireball EL — особый тип жестких дисков Quantum, жесткие диски Quantum Fireball EL объемом 5,1 Гбайт — особый тип жестких дисков Quantum Fireball EL и т. д.
В данной аналогии абстрактный жесткий диск является базовым классом, жесткие диски фирмы Quantum образуют подкласс класса жестких дисков, жесткие диски Quantum Fireball EL — подкласс класса жестких дисков фирмы Quantum и т. д. Подкласс называют также производным классом или классом-потомком. Для него класс, расположенный выше в иерархии, является базовым, подклассом или родительским классом. В нашем примере объект (конкретный жесткий диск) является составной частью структуры под названием "персональный компьютер", и обладает своими свойствами в силу принадлежности к определенному типу дисков Quantum Fireball EL 5,1 Гбайт, отличающемуся по своим характеристикам от других типов жестких дисков.
Действие, которое можно выполнить над данными, определяет метод. Он представляет собой подпрограмму. Различают методы класса и методы объекта. Последние могут применяться к любому объекту класса. Методы класса, называемые также статическими методами, не зависят от отдельного экземпляра, они применяются к целому классу как к отдельному объекту.
Для создания объектов применяются специальные статические методы, называемые конструкторами.
Для корректного удаления объектов используются специальные методы, называемые деструкторами.
Термин наследование в ООП обозначает способность классов наследовать свойства и методы у своих родительских классов.
Термин полиморфизм в ООП обозначает свойство класса-потомка переопределять методы родительского класса.
Инкапсуляция, наследование, полиморфизм — базовые понятия, лежащие в основе объектно-ориентированного программирования. Объектно-ориентированный подход возник в результате непрекращающихся попыток человека преодолеть сложность окружающего мира, проявляющуюся в любых областях деятельности. Он предлагает более естественный способ разделения сложной задачи на ряд более простых, используя понятие объекта, сочетающего данные и действия над ними. Он также позволяет экономить усилия, связанные с написанием программного кода, так как однажды созданные методы не нужно переписывать — они просто наследуются производными классами. Идея повторного использования кода в своем развитии проходит ряд этапов: подпрограмма, библиотека, модуль, класс.
В этой главе мы рассмотрим, каким образом основные концепции объектно-ориентированного программирования реализованы в языке Perl.
В языке Perl нет специального синтаксиса для описания классов, объектов или методов. Для их реализации используются уже знакомые нам синтаксические конструкции. Класс в Perl представляет собой пакет, объект является ссылкой, а метод — обычной подпрограммой.
В качестве пакета каждый класс имеет собственное изолированное пространство имен и таблицу символов, реализованную в виде хеш-массива. К переменным класса можно обращаться, используя их квалифицированные имена, содержащие в качестве префикса имя класса, за которым следуют два двоеточия, например, $CLASSNAME: :var. Для того чтобы пакет стал классом, в нем нужно определить специальную подпрограмму — конструктор, которая используется для создания отдельных экземпляров класса — объектов (см. ).
Объект в Perl представляет собой просто ссылку, но не любую, а связанную с определенным классом. Тип ссылки можно определить при помощи функции ref EXPR, которая, рассматривая свой аргумент как ссылку, возвращает символическое обозначение ее типа. Для встроенных типов Perl используются следующие символические обозначения:
REF — ссылка на ссылку;
SCALAR — ссылка на скаляр;
ARRAY — ссылка на массив;
HASH — ссылка на ассоциативный массив;
CODE — ссылка на подпрограмму;
GLOB — ссылка на переменную типа typegiob.
Для ссылки-объекта функция ref () возвращает имя класса, к которому этот объект принадлежит. Обычная ссылка становится объектом после ее "посвящения" в члены класса при помощи функции
bless REF [, CLASSNAME]
Слово "bless" в английском языке имеет значение "освящать, благословлять". В данном контексте его можно перевести как "посвящать" или "санкционировать". Функция bless REF санкционирует принадлежность субъекта ссылки REF к классу CLASSNAME. Она возвращает ссылку на этот субъект, но уже другого типа — CLASSNAME (напомним, что в главе 9 субъектом ссылки мы условились называть то, на что она указывает, т. е. собственно структуру данных некоторого типа). Она связывает обычную ссылку с именем класса. Если имя класса не задано, то используется имя текущего класса. После выполнения функции bless ок созданному ей объекту можно обращаться, используя его квалифицированное имя $CLASSNAME: :REF. Сказанное иллюстрируется следующим примером.
$h = { }; •
print("тип переменной \$h - ". ref($h), "\n");
bless($h, "MyClass");
print("тип переменной \$h - ". ref($h), "\n");
В результате будет выведен тип переменной $ref до и после вызова функции bless ():
тип переменной $h — HASH тип переменной $h — MyClass
Наследование в Perl отличается от наследования в других объектно-ориентированных языках программирования тем, что наследуются только методы. Наследование данных реализуется программистом самостоятельно. Наследование методов реализовано следующим образом. С каждым пакетом ассоциирован свой специальный массив @ISA, в котором хранится список базовых классов данного пакета. Таким образом, подкласс располагает информацией о своих базовых классах. Если внутри текущего класса встречается обращение к методу, не определенному в самом классе, то интерпретатор в поисках отсутствующего метода просматривает классы в том порядке, в котором они встречаются в массиве @ISA. Затем просматривается предопределенный класс UNIVERSAL. В нем изначально нет никаких явных определений, но автоматически содержатся некоторые общие методы, которые неявно наследуются всеми классами. В этом смысле класс UNIVERSAL можно считать базовым классом всех остальных классов.
Если метод не найден ни в одном из просмотренных классов, они вновь просматриваются в том же порядке в поисках подпрограммы AUTOLOAD (см. ). Если таковая обнаружена, она выполняется вместо вызванного несуществующего метода с теми же параметрами. Квалифицированное имя несуществующего метода при этом доступно через переменную
$AUTOLOAD.
Конструкторы
Конструкторы
Конструктор — это просто подпрограмма, возвращающая ссылку. Обычно (но не обязательно) конструктор имеет имя new. Выше мы сказали, что объект является ссылкой. Конструктор, создающий объект, то есть ссылку, тоже возвращает ссылку. О каких ссылках идет речь, на что они указывают? Рассмотрим простой пример.
package MyClass; sub new {
my $class = shift;
my $self = {} ;
bless $self, $class;
return $self; -""'
} ^
В операторе my $seif = {} создается ссылка на 7 анонимный хеш-массив, первоначально пустой, которая сохраняется в локальной переменной $seif. Функция bless о "сообщает" субъекту ссылки sseif, то есть анонимному хеш-массиву, что он отныне является объектом класса MyClass, и возвращает ссылку на этот объект. Затем ссылка на новый объект класса MyClass возвращается в качестве значения конструктора new (). Обратите внимание на следующие обстоятельства.
Во-первых, объект класса MyClass представлен анонимным хеш-массивом. Это обычный, хотя и не обязательный, способ представления объекта. Преимущество использования для этой цели хеш-массива заключается в том, что он может содержать произвольное число элементов, к которым можно обращаться по произвольно заданному ключу. Таким образом, все данные объекта сохраняются в указанном хеш-массиве. В некоторых случаях для представления объекта может использоваться другой тип данных, например массив, скаляр.
Во-вторых, обязательным для конструктора является обращение к функции bless о. Внутри подпрограммы-конструктора функцию bless о следует применять с двумя аргументами, явно указывая имя класса. В этом случае конструктор может быть наследован классом-потомком. Конструктор определяет, объект какого именно класса он создает, используя значение своего первого аргумента. Первым аргументом конструктора должно быть имя класса.
В-третьих, конструктору, создающему объект, в качестве первого аргумента передается имя класса этого объекта.
f Модуль класса Staff.pm: package Staff; require Exporter; 8ISA = qw(Exporter); SEXPORT = qw(new); sub new {
my ($class,@items) = shift;
my $self = {};
bless $self, $class;
return $self; }
# Основная программа:
#!/usr/bin/perl use Staff;
$someone=new(Staff) ; ${$someone}{"имя"}="Александр"; ${$someone}{"фамилия"}="Александров"; ${$someone}{"возраст"}="37"; for $i (sort keys %{$someone}) { print "$i=>$$someone{$i}\n"; }
В данном примере класс staff служит для представления анкетных данных. В качестве внутренней структуры для представления объекта наилучшим образом подходит хеш-массив, так как в него при необходимости можно добавлять новые элементы с произвольно заданными ключами, например, "имя", "фамилия", "образование" и т. д. Класс оформлен в виде отдельного модуля, способного управлять экспортом своих методов. Чтобы конструктор new () можно было вызвать в основной программе, он включен в файл экспорта @EXPORT. В результате вызова конструктора возвращается ссылка на объект класса. Значения элементов хеш-массива выводятся:
возраст => 37
имя => Александр
фамилия => Александров
Методы
Методы
Методы в Perl являются обычными подпрограммами. Начнем их изучение с методов, которые обязательно должны быть определены в каждом классе. Такими методами являются конструкторы. Знакомство с ними позволит лучше понять, каким способом в языке Perl представляются объекты.
Методы класса и методы объекта
Методы класса и методы объекта
Различают методы класса и методы объекта, которые называют также статическими и виртуальными, соответственно. Первым аргументом метода должна быть ссылка, представляющая объект, или имя пакета. То, каким образом каждый метод обрабатывает свой первый аргумент, определяет, является ли он методом класса или методом объекта.
Статические методы применяются к целому классу, а не к отдельным его объектам. В качестве первого аргумента статическому методу передается имя класса. Типичным примером статических методов являются конструкторы. В Perl методы выполняются в пространстве имен того пакета, в котором они были определены, а не в пространстве имен пакета, в котором они вызваны. Поэтому статические методы часто свой первый аргумент игнорируют, так как и без него известно, к какому пакету метод принадлежит. Последнее не относится к конструкторам, передающим свой первый аргумент функции Ыезз () в качестве имени класса.
Методы объекта применяются к отдельному объекту. Их первым аргументом должна быть ссылка, указывающая на объект, к которому применяется данный метод. Методы объекта могут выполнять разные действия, но наиболее типичными являются действия, связанные с отображением и изменением данных, инкапсулированных в объекте. В примере 13.2 мы присвоили значения, а затем их распечатали, обращаясь к данным объекта напрямую. Таким способом мы просто продемонстрировали, что конструктор действительно возвращает ссылку, представляющую объект. В действительности это плохой способ, и применять его не рекомендуется. В некоторых объектно-ориентированных языках программирования прямой доступ к данным объекта вообще невозможен. Объект следует рассматривать как "черный ящик", содержимое которого можно получить или изменить, только используя методы объекта. Такое ограничение помогает сохранить целостность и скрыть некоторые внутренние данные объекта. Отредактируем текст примера 13.2, дополнив его методами, которые используются для изменения и просмотра данных.
# Модуль класса Staff.pm:
package Staff;
require Exporter;
@ISA = qw(Exporter);
8EXPORT = qw(new showdata setdata);
sub new {
my ($class, $data) = @_;
my $self = $data;
bless $self, $class;
return $self; } sub showdata {
my $self = shift;
my @keys = @_ ? @_ : sort keys %$self;
foreach $key (@keys) {
print "\t$key => $self->{$key}\n";
}
return $self;
}
sub setdata {
my ($self,$data) = @_; for $i (keys %$data) {
$self->{$i)=$data->{$i);
}
return $self;
}
В данном примере по сравнению с предыдущим изменен конструктор new (). Теперь второй параметр, представленный локальной переменной $data, содержит ссылку. Эту ссылку функция bless () свяжет с классом staff, превратив в его объект. Таким образом, при помощи этого параметра можно управлять типом внутренней структуры данных, которая и представляет объект. Это может быть ссылка на хеш-массив, массив, скаляр и т. д. Параметры, передаваемые конструктору, называют переменными объекта. Они используются для того, чтобы установить начальные значения данных каждого вновь создаваемого объекта.
Если обратиться к основной программе:
#!/usr/bin/peri
use Staff;
$someone=new(Staff, ("имя"=>"","фамилия"=>""});
setdata($someone,{"имя"=>"Максим","фамилия"=>"Исаев",
"возраст"=>42,"занятия спортом"=>"теннис"}); showdata($someone);
то будут выведены следующие данные:
возраст => 42
занятия спортом => теннис
имя => Максим
фамилия => Исаев
В разных ситуациях один и тот же метод может выступать как метод класса или как метод объекта. Для этого он должен "уметь" определить тип своего первого аргумента: если аргумент является ссылкой, то метод действует как метод объекта, если именем пакета, то есть строкой, то как метод класса. Подобную информацию можно получить при помощи функции ref (). Она возвращает значение ЛОЖЬ (пустая строка), если ее аргумент не является ссылкой, то есть объектом. В противном случае функция ref о возвращает имя пакета, принадлежность к которому была для данного объекта санкционирована функцией bless ().
Объектно-ориентированное программирование в языке Perl
Объектно-ориентированное программирование в языке Perl
Обобщающий пример
Обобщающий пример
В заключение рассмотрим небольшой пример, поясняющий некоторые вопросы, рассмотренные в этой части.
#!/usr/bin/perl package Staff; sub new {
my ($class, $data) = @_;
my $self = $data;
bless $self, $class;
return $self; } sub setdata {
my ($self,$data) = @_;
for $i (keys %$data) {
$self->{$i}=$data->{$i};
}
return $self; } sub showdata {
my $self = shift;
my @keys = @_ ? @_ : sort keys %$self;
fоreach $key (@keys) {
print "\t$key => $self->{$key}\n";
}
return $self; } sub AUTOLOAD {
print "пакет Staff: отсутствует функция $AUTOLOAD\n"; } sub DESTROY {
print "Удаляется объект класса Staff\n"; }
######################################
package Graduate; @ISA = (Staff); sub new {
my ($class, $data) = @_;
# наследование переменной объекта
my $self = Staff->new($data);
$self->{"образование"}="высшее";
bless $self, $class;
return $self; } sub showdata {
my $self = shift;
return $self if ($self->{"образование"} no "высшее");
my @keys = sort keys %$self;
foreach $key (@keys) {
print "\t$key => $self->{$key}\n";
}
return $self; } sub DESTROY {
my $self= shift;
$self->SUPER::DESTROY;
print "Удаляется объект класса Graduate\n";
######################################
package main;
$someone=Graduate->new({ "фамилия" => "Кузнецов", "имя" => "Николай" });
$somebody=Staff->new({"фамилия" => "Петрова", "имя" => "Анна"});
$someone->showdata;
$somebody->Graduate::showdata;
$someone->getdata;
Для простоты все классы расположены в одном файле. Если класс занимает отдельный модуль, необходимЬчхрзабхшпъся об управлении экспортом имен при помощи списков @EXPORT и @EXPORT_OK, а также о подключении соответствующих модулей к вызывающей программе (см. ).
В данном примере определен пакет main и два класса: staff и Graduate, staff является базовым классом Graduate.
Наследование методов задается при помощи массива @ISA, ассоциированного с производным классом Graduate. Помимо наследования методов, которое обеспечивает Perl, организовано наследование переменных, объекта через вызов в конструкторе класса Graduate конструктора базового класса staff. В результате объект класса Graduate получает при создании переменную объекта staff (параметр, переданный конструктору new), которую изменяет, добавляя в соответствующий хеш-массив новый элемент с ключом "образование" и значением "высшее".
Ситуация, когда конструктор производного класса вызывает конструктор базового, также обсуждалась . В подобном случае при удалении объекта автоматически вызывается только деструктор производного класса, хотя при вызове конструктора последовательно создавались объекты двух классов. В примере деструктор DESTROY класса Graduate вызывает деструктор базового класса. В данном случае это совершенно не обязательно, так как оба деструктора просто выводят сообщения об удалении своих объектов, но ведь это только модель. В иной ситуации такое решение может быть необходимым.
Следующая тема связана с поиском несуществующего метода, к которому происходит обращение внутри класса, и применением в этом случае функции AUTOLOAD. В пакете main вызывается метод getdata. для объекта $someone. $someone является объектом Класса Graduate, в котором метод getdata не определен. Обратите внимание на форму вызова метода getdata. Если бы он был вызван в виде getdata ($someone), это означало, что вызывается функция getdata из пакета main с параметром $someone. Поскольку в пакете main такая функция не определена, выполнение программы было бы завершено с выдачей сообщения вида:
Undefined subroutine Smain::getdata called at ...
Форма обращения $someone->getdata однозначно определяет, что вызывается не функция, а метод объекта. Следовательно, его надо искать сначала в собственном классе Graduate, а затем в классе staff, который определен в качестве базового для Graduate. В классе staff метод getdata также не определен, но определена функция AUTOLOAD, которая и вызывается вместо этого метода.
Полиморфизм, т. е. переопределение методов базового объекта, показан на примере метода showdata. Класс staff служит для порождения анкетных форм учета персонала. Его подкласс Graduate описывает подмножество таких форм только для лиц с высшим образованием. Конструктор класса Graduate автоматически добавляет в форму запись о наличии высшего образования. Метод showdata, наследованный у базового класса, изменен таким образом, чтобы игнорировать анкеты без такой записи. Поэтому информация об объекте $ somebody, принадлежащем к базовому классу, напечатана не будет.
В результате выполнения примера будут выведены строки, соответствующие действиям, заданным в программе:
имя => Николай образование => высшее фамилия => Кузнецов
пакет Staff: отсутствует функция Graduate::getdata Удаляется объект класса Staff Удаляется объект класса Graduate Удаляется объект класса Staff
Создайте класс, объект которого представляет
Упражнение
Создайте класс, объект которого представляет дерево файловой системы для заданного каталога и позволяет вывести это дерево с указанием всех вложенных каталогов и содержащихся в них файлов.
Как связаны между собой понятия
Вопросы для самоконтроля
1. Как связаны между собой понятия "объект" и "класс"?
2. Что такое инкапсуляция, наследование, полиморфизм в объектно-ориентированном программировании?
3. Как в языке Perl реализовано понятие "класс"?
4. Что представляет собой объект в языке Perl?
5. Для чего предназначена функция bless () ?
6. Как, по вашему мнению, связаны между собой понятия "класс", "пакет", "модуль"?
7. Как в Perl осуществляется наследование методов? Данных?
8. Какой синтаксис используется для объявления метода?
9. Чем конструкторы в Perl отличаются от других методов?
10. В чем разница между методами класса и методами объекта?
11. Какие формы вызова объекта вы знаете? В чем, по-вашему, заключаются их преимущества и недостатки?
12. Какие имена может иметь подпрограмма-деструктор?
13. Как можно реализовать переопределение метода базового класса (полиморфизм)?
14. Как осуществить наследование переменных объекта?
Вызов метода
Вызов метода
Существуют две синтаксические формы вызова как методов класса, так и методов объекта.
Первая форма имеет вид:
method class_or_object, parameters
например,
$somebody = new Staff, {"имя"=>"Анна"}; # метод класса
showdata $somebody, "имя","фамилия"; # метод объекта
showdata {"имя"=>"Мария","возраст"=>18}; # метод объекта
showdata new Staff "возраст"; # метод объекта
showdata setdata hew Staff, {"имя"=>"Глеб"}, "имя"; # метод объекта
Данная форма представляет собой обычный вызов функции, который может быть вложенным в другой вызов. Первым аргументом функции является ссылка (для методов объекта) или/им^Гпакета (для методов класса).
В приведенном примере первая строка содержит вызов конструктора new, в котором первым (и единственным) аргументом является имя пакета.
Вторая строка содержит вызов метода объекта, в котором первым аргументом является объект-ссылка.
В третьей строке первый аргумент задается при помощи блока {}, возвращающего ссылку на анонимный хеш-массив. Данный хеш-массив не будет объектом, так как он не объявлен объектом класса staff при помощи функции bless о, но синтаксически такая конструкция возможна.
В четвертой строке метод объекта вызывается с двумя аргументами. Первым аргументом является ссылка, возвращаемая конструктором new (), вторым — строка "возраст".
В пятой строке конструктор new создает объект, который передается в качестве первого аргумента методу setdata. Вторым аргументом метода setdata является ссылка на анонимный хеш-массив {"имя"=>"Глеб"). Метод showdata в качестве первого аргумента использует ссылку, возвращаемую методом setdata, а в качестве второго аргумента — строку "имя".
Вторая форма обращения к методу имеет вид
class_or_obj ect ->method(parameters)
Например, предыдущие вызовы могут быть записаны также в виде:
$somebody = Staff->new(("имя"=>"Анна"});
$somebody->showdata("имя","фамилия");
new Staff->showdata("возраст");
new Staff->setdata({"имя"=>"Глеб"})->showdata("имя");
Вторая форма требует обязательного заключения аргументов в скобки.
Замечание |
|
Как видим, обе формы записи могут быть достаточно сложными. В разных случаях любая из них может оказаться предпочтительной в смысле читаемости текста программы. Если нет серьезных оснований против, то рекомендуем использовать вторую форму, исходя из следующих соображений. |
$obj->{keyname}->method().
При употреблении первой формы могут возникнуть трудноопределимые ошибки. Например, если происходит обращение к методу в области Видимости одноименной функции, то при использовании первой формы вызова компилятор может вместо метода вызвать функцию. Вторая форма подобную ошибку исключает.
Для того чтобы вызвать метод определенного класса, следует перед именем метода указать имя пакета, как при вызове обычной подпрограммы. Например, чтобы вызвать метод, определенный в пакете staff, следует использовать запись вида:
$someone = new Staff;
Staff::showdata($someone, "имя");
В данном случае просто вызывается метод showdata из пакета staff. Ему передается в качестве аргумента объект $ some one и прочие аргументы. Если вызвать метод следующим образом:
$someone=new Staff; $someone->Staff::showdata("имя");
то это будет означать, что для объекта $ someone следует сначала найти метод showdata, начав поиск с пакета staff, а затем вызвать найденный метод с объектом $ someone в качестве первого аргумента. Напомним, что с каждым пакетом ассоциируется свой массив @ISA, содержащий имена других пакетов, представляющих классы. Если интерпретатор встречает обращение к методу, не определенному в текущем пакете, он ищет этот метод, рекурсивно (то есть включая производные классы) просматривая пакеты, определенные в массиве @ISA текущего пакета. Если подобный вызов делается внутри пакета, являющегося классом, то для того, чтобы указать в качестве начала поиска базовый класс, не указывая его имя явно, можно использовать имя псевдокласса SUPER:
$someone->SUPER::showdata("имя");
Такая запись имеет смысл только внутри пакета, являющегося классом.
Опции командной строки
Опции командной строки
При запуске интерпретатора peri из командной строки можно задать разнообразные режимы его работы. Это достигается передачей ему специальных опций, называемых еще переключателями или просто ключами, включающих или выключающих разные режимы работы интерпретатора. Знание всех возможностей, предоставляемых опциями, позволяет более эффективно использовать интерпретатор для решения возникающих задач. Например, опция -е позволяет задать строку кода Perl непосредственно в командной строке. Эта возможность удобна для быстрого выполнения небольшой задачи, не прибегая к созданию файла с исходным текстом программы. Другие опции могут сэкономить время системного администратора, позволив решить некоторые задачи непосредственным вызовом peri из командной строки без написания кода достаточно большого объема.
Внутренний отладчик, которым снабжен интерпретатор peri, неоценим при отладке сложных сценариев Perl, особенно при разработке собственных модулей. Конечно, по общему признанию апологетов Perl, возможности его отладчика не так изощренны, как в С, C++ или Visual Basic, однако они могут оказаться мощным средством выявления ошибок, не обнаруживаемых самим компилятором даже в режиме отображения предупреждений.
В этой главе мы познакомимся с некоторыми опциями командной строки интерпретатора и их использованием для решения повседневных задач системного администрирования. Узнаем, как можно воспользоваться встроенным отладчиком в системе UNIX, а также изучим необходимый набор команд отладчика для выполнения основных действий в процессе обнаружения ошибок программ Perl.
Наиболее общая форма синтаксиса строки запуска интерпретатора peri имеет следующий вид:
peri [опции] [—] [файл_программы] [параметры_программы]
Опции peri задаются сразу же после имени интерпретатора и представляют собой двухсимвольные последовательности, начинающиеся с дефиса "-":
peri -а -р prog.pl filel file2
Некоторым из них может потребоваться передать параметры, которые задаются непосредственно после соответствующих опций:
peri -w -I/usr/include -0055 prog.pl filel file2
Опции без параметров можно группировать, задавая целую группу с одним дефисом. Следующие вызовы peri эквивалентны:
peri -wd prog.pl filel file2 peri -w -d prog.pl filel file2
Опции с параметрами таким способом задавать нельзя. Можно, однако, одну опцию с параметром добавить в конец группы опций без параметров:
peri -wdl/usr/include -0055 prog.pl filel file2
Передать опции для установки соответствующего режима работы интерпретатора можно непосредственно и из самой программы Perl. Первая строка сценария со специальным комментарием #! предназначена именно для этой цели:
#!/usr/bin/perl -w -d -I/usr/include
Теперь настало время узнать, какие опции существуют и как они влияют на режим работы интерпретатора. Мы решили сначала перечислить все возможные опции peri, а потом объяснить использование некоторых из них для выполнения задач системного администрирования UNIX. В табл. 14.1 представлены все опции с их кратким описанием. Советуем читателю внимательно ознакомиться с содержанием этой таблицы, так как для некоторых опций приведенное краткое описание в то же время является и исчерпывающим для понимания существа данной опции.
Таблица 14.1. Опции командной строки
Опция |
Назначение |
-0 [nnn] |
Задает разделитель записей файла ввода, устанавливая значение специальной переменной $/. Необязательный параметр nnn — восьмеричный код символа; если отсутствует, принимается равным 0 (код символа \0). Эта опция удобна, если при каждом запускесценария Perl в него необходимо передавать файлы с разными символами завершения записи |
-а |
Включает режим авторазбиения строки ввода при совместном использовании с опцией -n или -р (строка передается функции split ( } , а результат ее выполнения помещается в специальный массив @г). Умалчиваемый разделитель — пробел; опция -F позволяет задать регулярное выражение для иного разделителя |
-с |
Проверка синтаксиса программы без ее выполнения (блоки BEGIN, END и use выполняются, так как это необходимо для процесса компиляции) |
-d[ : модуль] |
Запускает сценарий в режиме отладки под управлением модуля отладки или трассировки, установленного как Devel: : модуль |
-D [число/список] |
Устанавливает флаги отладки |
-е ' строка кода ' |
Выполнение строки кода Perl, заданной параметром этой опции, а не файла сценария файл_программы, указанного в командной строке вызова интерпретатора. В строке кода можно задать несколько операторов, разделенных символом ';'. Допускается задание нескольких опций -е. (В Windows строка кода задается в двойных кавычках и для использования самих кавычек в коде Perl необходимо применять управляющую последовательность \".) |
-F/per выраж/ |
Задает регулярное выражение для разделителя при автоматической разбивке строки файла ввода в случае задания опции -а. Например, -F/-.+/ определяет в качестве разделителя одно или более двоеточий. По умолчанию используется пробел / /. Символы "/" при задании per выраж не обязательны |
-i {расширение] |
Задает режим редактирования по месту файла, переданного как параметр в сценарий Perl. Используется совместно с опциями -n или -р. Редактирование выполняется по следующей схеме: файл переименовывается (если задано расширение), открывается файл вывода с именем исходного файла и все операции print ( ) сценария осуществляют вьшод в этот новый файл. Параметр расширение используется для задания имени копии файла по следующей схеме: если в нем нет символов "*", то оно добавляется в конец имени исходного файла; каждый символ "*" этого параметра заменяется именем исходного файла |
-Ткаталог |
Задает каталог поиска сценариев Perl, выполняемых операциями do, require и use (сохраняется как элемент специального массива @INC). Также задает каталоги размещения файлов, включаемых в сценарий Perl директивой finclude препроцессора С. Можно использовать несколько опций для задания необходимого количества каталогов поиска |
- 1 [ nnn ] |
Включает автоматическую обработку концов строк ввода. Работа в этом режиме преследует две цели: 1. Автоматическое удаление завершающего символа записи, хранящегося в специальной переменной $/, при включенном режиме -n или -р; 2. Присваивание специальной переменной $\, в которой хранится символ завершения записи при выводе операторами print, восьмеричного значения nnn, представляющего код символа завершения; если этот параметр не задан, то переменной $\ присваивается текущее значение $ / |
-m[-] мо дуль -М [ - ] модуль -[гаМ][-] модуль= пар! [ , пар2 ] . . |
Выполняет оператор use module О (опция -т) или use module (опция -м) перед выполнением сценария Perl. Если параметр модуль задан с дефисом, то use заменяется на по. Третья форма этих опций позволяет передать параметры в модуль при его загрузке |
-n |
Заданный сценарий Perl выполняется в цикле while (0) { сценарий Perl } Это позволяет обработать программой Perl в цикле каждую строку всех файлов, имена которых переданы в качестве параметров сценария Perl. Эта опция эмулирует функциональность sed с ключом -n и awk |
-Р |
Аналогичен опции -п, но добавляется печать каждой обрабатываемой строки, как в редакторе sed: while (<>) { сценарий Perl } continue { print or die "-p destination: $!\n"; } |
_Р |
Перед компиляцией сценарий Perl обрабатывается препроцессором С, что позволяет использовать в нем команды препроцессора #define, # include и все команды условной компиляции С (#if, felse и т. д.). В опции -I можно задать каталоги расположения файлов, включаемых командой t include |
-s |
Включает режим синтаксического анализа строки вызова сценария Perl на наличие после имени файла сценария, но до параметров имен файлов "пользовательских опций" (параметров, начинающихся с дефиса). Такие параметры извлекаются из массива @ARGV и в программе объявляются и определяются переменные с именами введенных опций. Следующий сценарий напечатает "Задана опция optl" тогда и только тогда, когда он будет вызван с опцией -optl: # ! /usr/bin/perl -s if ($optl) { print " Задана опция optl\n"; } |
-S |
Поиск файла программы Perl файл программы осуществляется с использованием значения переменной среды PATH |
-т |
Включает режим проверки на безопасность полученных извне данных в операциях с файловой системой. Полезен при реализации CGI-сценариев. Эта опция должна быть первой в списке опций интерпретатора peri, если она применяется к сценарию |
-u |
Создание дампа ядра после компиляции сценария Perl. Последующее использование программы undump позволяет создать двоичный выполняемый файл сценария |
_u |
Разрешает выполнение небезопасных операций. При использовании этой опции в UNIX программа Perl выполняется в незащищенном режиме и ей предоставляется полный доступ к файловой системе |
-V |
Отображает номер версии, а также другую важную информацию об интерпретаторе peri |
_V [ : переменная ] |
Отображает информацию конфигурации интерпретатора peri (расположение необходимых библиотек, значения переменных среды и т. д.). Если задано имя переменной среды, отображает ее установленное значение |
-W |
Включает режим отображения предупреждений во время компиляции программы Perl. Рекомендуется всегда применять эту опцию |
-х [каталог] |
Извлекает и выполняет сценарий Perl, расположенный в текстовом файле. Эта возможность удобна, если сценарий прислан по электронной почте. Интерпретатор сканирует файл, пока не найдет строку, начинающуюся с символов "# ! " и содержащую слово "peri". После этого выполняется сценарий до лексемы END . Если задан параметр каталог, то перед выполнением сценария он становится текущим |
Как видно из табл. 14.1, интерпретатор peri располагает достаточно большим набором опций, разработанных специально в помощь системному администратору UNIX. Эти опции позволяют решать задачи, даже не прибегая к созданию текстового файла сценария Perl.
Одной из наиболее часто встречающихся задач системного администрирования является задача обработки содержимого большого числа файлов и данных (например, изменение значений некоторых переменных среды в конфигурационных файлах). Можно написать сценарий Perl, в цикле обрабатывающий строки переданных ему файлов, а можно воспользоваться опциями -п или -р, которые организуют цикл по файлам, и задать необходимые действия для каждой строки файла в опции -е. Таким образом, быстрота решения задачи гарантирована!
Итак, мы хотим в конфигурационных файлах configl, config2 и configS, содержащих строки вида ключ = ЗНАЧЕНИЕ, изменить значение ключа "кеу!" на величину 5. Эта задача решается следующим вызовом peri из командной строки:
peri -p -i.bak -e"m/ (\w+)\s*=\s*(.+)/i;
if($l eq V'KeylV){$_ = \"$1 = 5\n\";};" configl config2 configS
Несколько комментариев к строке вызова интерпретатора peri. В ней использованы опции -р и -i для обработки содержимого конфигурационных файлов по месту (опция -i, причем задано расширение .bak для копий исходных файлов) в неявном цикле с печатью] (опция -р). Код модификации содержимого файлов задается с помощью о/щии -е. Он достаточно прост. Строка файла, прочитанная в специальнуюЛтеременную Perl $_, проверяется на содержание подстроки вида ключ = ЗНАЧЕНИЕ. В регулярном выражении определены две группы: первая соответствует ключу, а вторая — его значению. Таким способом мы сохраняем имя ключа и его значение в специальных переменных $1 и $2, соответственно. Второй оператор кода, в случае совпадения имени ключа с заданным, заносит в переменную $_ строку с новым значением ключа (кеу! = 5).
Как выполняется этот сценарий? Создается копия исходного конфигурационного файла configl (файл configl.bak) и новый пустой файл с именем configl. Последовательно в переменную $_ читаются строки из файла-копии, а в переменную $1 заносится имя ключа, если таковой обнаружен оператором т/.../. Если имя ключа равно "Keyi", то в переменной $_ формируется строка задания нового значения ключа. Перед чтением следующей строки файла configl.bak в файл configl записывается содержимое переменной $_. Эта процедура выполняется со всеми заданными конфигурационными файлами. В результате выполнения этой программы формируются конфигурационные файлы, в которых значение ключа Keyi изменено на 5.
Опция - р достаточна полезна для анализа содержимого файлов. Например, следующая команда отобразит на экране содержимое файла prog.pl:
peri -p -е"1" prog.pl
Замечание |
|
Задание кода программы Perl при работе с интерпретатором peri является необходимым действием. Его можно задать, указав имя файла программы после всех опций, либо непосредственно в командной строке в опции -е. При печати содержимого файла мы задали в командной строке программу из одного оператора, который, по существу, ничего не делает. |
peri -p -e "s/\s*.+\s(.+)\s*/$l\n/;" test.dat
Замечание |
|
При использовании опции -р следует помнить, что она печатает содержимое специальной переменной $_. Поэтому информацию, подлежащую отображению, следует помещать именно в эту переменную, как в последнем примере. |
Отладчик Perl
Отладчик Perl
Написав программу и устранив ошибки компиляции, любой программист втайне надеется, что она будет работать именно так, как он и задумывал. Практика, однако, в большинстве случаев совершенно иная: при первом запуске программа работает, но выполняет не совсем, а иногда и совсем не то, что надо; при одних исходных данных она работает идеально, а при других "зависает". И это случается не только с начинающим, но и с опытным программистом. В таких случаях на помощь приходит отладчик — специальная программа, которая позволяет программисту, обычно в интерактивном режиме, предпринять определенные действия в случае возникновения необычного поведения программы.
Для вызова встроенного отладчика интерпретатора peri его необходимо запустить с опцией -d (задав ее либо в командной строке, либо в строке специального комментария I! самой программы). Отладчик инициируется, когда начинает выполняться сценарий Perl. При этом отображается версия отладчика, первая выполняемая строка кода программы и его приглашение DB<I> на ввод команд пользователя:
Loading DB routines from perl5db.pl version 1.0402 Emacs support available.
Enter h or *h h' for help.
main::(examplel.pl:3): print "\000\001\002\003\004\005\006\007\n"; DB<1>
После чего можно вводить команды отладчика для выполнения определенных действий: установить точки останова, определить действия при выполнении определенной строки кода Программы, посмотреть значения переменных, выполнить часть кода сценария и т. д. Эта глава и посвящена краткому описанию команд, задающих необходимые действия при отладке разработанного сценария Perl. Мы здесь не учим стратегии поиска ошибок, а только лишь показываем возможности отладчика при ее реализации.
Замечание | ||
Все, что здесь говорится о встроенном отладчике, относится к пользователям системы UNIX. Тот, кто работает в системах семейства Windows и пользуется интерпретатором peri фирмы ActiveState, может совсем не читать этот раздел, так как интерпретатор этой фирмы снабжен отладчиком, работа с которым осуществляется через графический интерфейс пользователя, а не с помощью командной строки. Хоти ничто не мешает таким пользователям воспользоваться встроенным отладчиком, аналогичным отладчику интерпретатора peri для UNIX, и работать с ним из командной строки. Для этого следует воспользоваться командным файлом cmddb.bat, расположенным в каталоге \perl520\debugger. |
Просмотр текста программы
Просмотр текста программы
При загрузке отладчика отображается первая строка кода программы Perl. Но для выполнения определенных действий (установки точки останова, задания определенных действий при выполнении конкретного оператора Perl и т. д.) нам необходимо видеть текст программы. Как это осуществить? В отладчике для подобных действий предусмотрен ряд команд.
Команда i отображает на экране монитора 10 строк текста программы, расположенных непосредственно за последней отображенной строкой. Последовательное выполнение этой команды позволяет быстро пролистать текст программы. Вызов команды i с указанием номера строки отобразит ее содержимое. Несколько последовательных строк программы можно увидеть, задав в команде i через дефис номер начальной и конечной строки. Например, команда 1 1-5 отобразит пять строк программы:
DB<5> 1 1-5 1 #! peri -w
2==> open FILE, "books" or die $!; 3: open REPORT, ">report"; 4 5: select REPORT;
Обратите внимание, что отладчик отображает не только содержимое строк, но и их номера, причем после номера строки с первым выполняемым оператором следует стрелка, а номер каждой последующей выполняемой строки завершается символом двоеточие ":". В угловых скобках приглашения отладчиков <5> отображается порядковый номер выполненной команды от начала сеанса отладки.
Команда w отобразит блок, или окно строк — три строки до текущей, текущая строка и шесть после текущей. Текущей в отладчике считается строка программы после последней отображенной. Если команде w передать номер строки, то отобразится окно строк относительно заданной строки текста — три строки до заданной, сама заданная строка и шесть после нее.
Последняя команда отображения текста программы — команда - (дефис), которая отображает 10 строк текста, предшествующих текущей строке.
Просмотр значений переменных
Просмотр значений переменных
В процессе отладки можно посмотреть значение любой переменной программы в любой момент времени. Команда
V [пакет [переменная]]
отображает значение заданной переменной указанного пакета. Выполненная без параметров, она отображает значения всех переменных программы из всех пакетов.
При работе с этой командой следует иметь в виду, что при задании переменной, значение которой необходимо посмотреть, не надо задавать никакого префикса, а только идентификатор переменной. Отладчик отобразит значения всех переменных указанного пакета с заданным идентификатором. Например, если в программе определена скалярная переменная $ref, маесив скаляров @ref и хеш-массив %ref, то выполнение команды v main ref приведет к следующему результату:
DB<1> V main ref $ref = 24 @ref = ( 1
01
1 2 | ) %ref = (
'One' => 1
'Two' => 2 )
Команда х аналогична команде v, но она отображает значения переменных текущего пакета. Ее параметром является идентификатор переменной, имя пакета указывать не надо. Вызванная без параметров, она отображает значения всех переменных текущего пакета. Например, команда х ref отобразит значения переменной $ref, массива @ref и хеш-массива %ref текущего пакета, внутри которого приостановлено выполнение программы. По умолчанию программа выполняется в пакете main.
Команда t работает как переключатель, включая режим отображения строк выполняемого кода (режим трассировки) или выключая его:
DB<11> t Trace = on
DB<11> с 5
main::(example2.pl:3): @ref = (1,2,3,4); main::(example2.pl:4): %ref = ("One",l, "Two",2); main::(example2.pl:5): $_ = " qwerty \t\tqwerty";
DB<12> t Trace = off
DB<12> с 7 main::(example2.pi:7): mySub();
DB<13>
Обратите внимание, что при включенном режиме трассировки отображаются все строки выполняемого кода, тогда как после его выключения, отображается только следующий, подлежащий выполнению оператор.
Точки останова и действия
Точки останова и действия
В процессе отладки программы возникает необходимость приостановить ее выполнение в определенных подозрительных иестах, посмотреть значения
переменных и предпринять дальнейшие действия по отладке кода. Нам уже известна команда с отладчика, которая непрерывно выполняет код программы до первой встретившейся точки останова, но как задать ее?
Для этих целей служит команда ь (сокращение от английского глагола break — прервать) отладчика. Ее параметром является номер строки кода, в которой устанавливается точка останова: отладчик приостановит выполнение программы Perl перед заданной строкой. Если команда ь вызывается без параметра, то точка останова определяется в текущей строке.
Можно определить точку останова в первой строке кода подпрограммы. Для этого команде b необходимо передать в качестве параметра имя подпрограммы. Например, следующая команда
DB<11> b mySub
I устанавливает точку останова в первой строке кода подпрограммы mySub.
Иногда необходимо, чтобы выполнение программы приостанавливалось в некоторой точке программы только при выполнении каких-либо условий (например, равенства заданному числу значения какой-нибудь переменной, или совпадения значений двух других переменных и т. п.). Команда ь позволяет задавать подобные условные точки останова. Для этого ей можно передать в качестве второго параметра условие, при истинности которого точка останова будет восприниматься отладчиком как действительная точка останова. Если условие перед выполнением строки кода не будет истинно, то останова программы в этой точке не произойдет. Например, следующая команда
DB<1> b 4 $r==l I
определяет условную точку останова в строке 4. Отладчик приостановит выполнение программы перед этой строкой по команде с только, если значение переменной $г будет равно 1.
Команда L отображает список всех установленных точек останова, как безусловных, так и условных:
DB<1> b 4 $г==1 DB<2> b 6 DB<3> L
Iexample2.pl: . •:.,-. , 4: %ref = ("One",!, "Two",2);
break if ($r==l) 6: @s = split;
break if (1) •/;•;'• : • -
Отображаемая информация о точке останова представляет номер строки и код Perl, а также условие, при котором действует точка останова (break if (УСЛОВИЕ)). Для безусловной точки останова условие всегда истинно и равно 1.
Для удаления точки останова достаточно выполнить команду d с параметром, равным номеру строки, в которой определена точка останова. Команда о удаляет все точки останова, определенные в сеансе работы с отладчиком.
Полезно при отладке программы задать действия, которые будут предприняты перед выполнением операторов определенной строки. Например, напечатать значения каких-либо переменных или изменить их при выполнении некоторого цикла. Подобное поведение программы можно реализовать, задав действия командой а. Два ее параметра определяют строку кода и сами действия (обычный оператор Perl) перед началом выполнения операторов заданной строки:
а 75 print "*** $ref\n";
Можно задать несколько операторов для выполняемых действий, однако следует учитывать, что это может привести к смешению отображаемой на экране монитора информации из самой программы и установленных действий.
Любое действие можно выполнить немедленно, набрав код в строке приглашения отладчика DBO. Подобные действия не изменяют текст программы (операторы действий не записываются в ее файл), но позволяют создавать новые переменные и использовать их в вычислениях. Правда, по завершении сеанса отладки подобная информация пропадает.
Мы познакомили читателя лишь с основными командами отладчика, наиболее важными и полезными, с нашей точки зрения, для процесса поиска ошибок. Их полный набор с краткими описаниями представлен в табл. 14.2. Более подробную информацию можно всегда найти в документации, с которой распространяется Perl, или из различных ресурсов Internet.
Таблица 14.2. Основные команды отладчика
Команда |
Описание |
m |
Отображается содержимое стека вызванных подпрограмм |
s |
Пошаговое выполнение программы (с заходом в подпрограммы) |
n |
Пошаговое выполнение программы (без захода в подпрограммы) |
<Enter> |
Повтор последней команды s или п |
r |
Завершение текущей подпрограммы и возврат из нее |
с [строка] с [подпрогр] |
Непрерывное выполнение кода программы до первой точки останова или указанной строки, или подпрограммы |
1 строка+число |
Отображает число плюс одну строку кода, начиная с заданной строки — |
1 строка!-строка2 |
Отображает диапазон строк: от строки с номером строка! до строки с номером строка2 |
1 строка |
Отображает заданную строку |
1 подпрогр |
Отображает первый блок строк кода подпрограммы |
1 |
Отображает следующий блок из 10 строк |
- |
Отображает предыдущий блок из 10 строк |
w [строка] |
Отображает блок строк вокруг заданной строки |
• |
Возврат к выполненной строке |
f файл |
Переключение на просмотр файла. Файл должен быть загружен |
/образец/ |
/ Поиск строки по образцу; направление вперед от текущей строки. Завершающая косая черта не обязательна |
?образец? |
Поиск строки по образцу; направление назад от текущей строки. Завершающий символ "?" не обязателен |
L |
Отображение всех установленных точек останова |
S [ [ ! ] образец] |
Отображение имен подпрограмм, [не] соответствующих образцу |
t |
Включение/выключение режима трассировки |
b [строка] [условие] |
Установка точки останова в заданной строке и условия ее действия |
b подпрогр [условие] |
Установка точки останова в первой строке подпрограммы и условия ее действия |
b load файл |
Установка точки останова на операторе require файл |
b postpone подпрогр [условие] |
Установка точки останова в первой строке подпрограммы после ее компилирования |
b compile подпрогр |
Остановка после компилирования подпрограммы |
Для удобства и ускорения отладки больших программ в интерпретаторе per! предусмотрен встроенный отладчик. Его команды позволяют приостанавливать выполнение сценария Perl в подозрительных точках, задавать определенные действия при выполнении кода программы, просматривать стек вызова подпрограмм, менять в цикле значения переменных программы и многие другие полезные при поиске ошибок действия. Использование отладчика ускоряет процесс разработки программ Perl.
Какую функцию выполняют опции интерпретатора
Вопросы для самоконтроля
1. Какую функцию выполняют опции интерпретатора peri?
2. Какие существуют способы задания опций интерпретатора?
3. Перечислите наиболее полезные опции для выполнения задач, связанных с системным администрированием в UNIX.
4. Зачем нужен отладчик и как его инициировать?
5. Перечислите основные действия, которые позволяет выполнять отладчик в процессе отладки программы Perl.
Выполнение кода
Выполнение кода
Команда s предназначена для последовательного пошагового выполнения программы: каждый ее вызов выполняет следующую строку кода. Эта строка должна выполняться в программе без изменения потока выполнения операторов. После выполнения очередной строки кода отображается строка, которая должна быть выполнена следующей:
DB<1> s main: : (exaitple2.pl:3) : @s = split;
При следующем выполнении команды s будет выполнена отображенная строка программы: @s = split;.
Если следующая выполняемая строка кода расположена в модуле, код которого доступен (например, вызов подпрограммы), то осуществляется переход в него, соответствующая строка кода выполняется и отладчик приостанавливает выполнение программы до ввода следующей программы. Последующие команды s будут построчно выполнять код подпрограммы, пока не выполнится последняя строка ее кода. Таким образом, команда s позволяет выполнять подпрограмму с заходом в нее.
Команда п работает аналогично команде s, последовательно выполняя строки кода программы, за одним исключением — она выполняет код подпрограммы без захода в него, т. е. код подпрограммы выполняется полностью, и при следующем вызове команды п выполняется оператор строки кода, непосредственно следующей за строкой с вызовом подпрограммы. Таким образом, команда п позволяет "обойти" пошаговое выполнение операторов подпрограммы.
Совет
Если мы осуществляем пошаговое выполнение программы (командами s или n), то нажатие клавиши <Enter> эквивалентно вызову последней команды s или n.
Если мы в процессе отладки попали в тело подпрограммы (после, например, выполнения очередной команды s), то командой г можно немедленно завершить ее выполнение. Выполнение программы приостанавливается на первом после вызова подпрограммы операторе в ожидании очередной команды пользователя.
Пошаговое выполнение программы командами s и п может оказаться утомительным делом при отладке кода большого объема. В отладчике Perl предусмотрена команда с, которая выполняет программу от текущего оператора до первой встретившейся точки останова или до завершения программы, если точки останова на соответствующем участке кода не определены.
Эта же команда позволяет выполнить программу от текущей строки до определенной строки кода программы. Для этого необходимо в вызове команды с указать номер строки, до которой должна выполниться программа, если только не встретится точка останова.
CGI-сценарии
CGI-сценарии
Назначение CGI-программы — создать новый HTML-документ, используя данные, содержащиеся в запросе, и передать его обратно клиенту. Если такой документ уже существует, то передать ссылку на него. Какой язык можно использовать для написания CGI-программ? Сам интерфейс CGI не накладывает ограничений на выбор языка программирования. Зная, какую задачу решает CGl-программа и каким образом она получает входную информацию, мы можем назвать свойства, которыми должен обладать язык CGI-программирования.
Средства обработки текста. Необходимы для декодирования входной информации, поступающей в виде строки, состоящей из отдельных полей, разделенных символами-ограничителями.
Средства доступа к переменным среды. Необходимы, так как с помощью переменных среды данные передаются на вход CG.I-программы.
Возможность взаимодействовать с другими программами. Необходима для обращения к СУБД, программам обработки графики и другим специальным программам.
Выбор языка зависит и от операционной системы Web-сервера. Большая часть имеющихся серверов предназначена для работы под управлением операционной системы UNIX. Учитывая эти соображения, мы можем заключить, что язык Perl, обладающий развитыми средствами обработки текста и создания сценариев, первоначально созданный для работы в ОС UNIX и перенесенный на множество других платформ, является наиболее подходящим средством создания сценариев CGI. Кроме того, CGI-програм-мирование на языке Perl имеет поддержку в виде готовых модулей CPAN, свободно доступных в сети Internet.
CGI-сценарий на языке Perl — это программа, имеющая свою специфику. Она, как правило, генерирует HTML-документ, посылаемый клиенту в виде ответа сервера. Ответ сервера, так же, как и запрос клиента, имеет определенную структуру. Он состоит из следующих трех частей:
1. Строка состояния, содержащая три поля: номер версии протокола HTTP, код состояния и краткое описание состояния, например:
НТТР/1.0 200 OK f запрос клиента обработан успешно
НТТР/1.0 404 Not Found # Документ по указанному адресу не существует
2. Заголовки ответа, содержащие информацию о сервере и о возвращаемом HTML-документе, например:
Date: Mon, 26 Jul 1999 18:37:07 GMT # Текущая дата и время
Server: Apache/1.3.6 ::,, •.# Имя и номер версии сервера
Content-type: text/html tt Описывает медиа-тип содержимого
3. Содержимое ответа — HTML-документ, являющийся результатом выполнения CGI-программы.
CGI- программа передает результат своей работы (HTML-документ) серверу, который возвращает его клиенту. При этом сервер не анализирует и не изменяет полученные данные, он может только дополнять их некоторыми заголовками, содержащими общую информацию (например, текущая дата и время) и информацию о самом себе (например, имя и версия сервера). Информация о содержимом ответа формируется CGI-программой и должна содержать как минимум один заголовок, сообщающий браузеру формат возвращаемых данных:
Content-type: text/html
Замечание |
|
Информацию о заголовках можно найти в спецификации протокола HTTP. Мы же ограничимся еще одним примером. Если в качестве ответа клиенту посылается статический документ, например, подтверждение о получении заполненной формы, то неэффективно каждый раз создавать его заново. Лучше создать один раз и сохранить в файле. В этом случае CGI-сценарий вместо заголовка Content-type: media-type, описывающего формат данных, формирует заголовок Location: URL, указывающий серверу местонахождение документа, который следует передать клиенту. |
Напишем простейший CGI-сценарий, посылающий пользователю HTML-страницу с приветствием
#!/usr/bin/perl
print "Content-type:text/html\n\n";
print "<html><head><title>HELLO</titlex/head>\n";
print "<body>\n";
print "<h2>Bac приветствует издательство ВХВ - Санкт-Петербург</п2>\п"; print "</bodyx/html>\n";
Если поместить файл hello.cgi в каталог CGI-программ Web-сервера, а затем обратиться к нему из браузера, то браузер отобразит HTML-документ, созданный программой hello.cgi (Рисунок 15.2).
Замечание |
|
Большинство Web- серверов по умолчанию предполагают, что файлы GGi-сце-нариев находятся в специальном каталоге, обычно называемом cgi-bin. Можно настроить сервер таким образом, чтобы все файлы, находящиеся в определенном каталоге, он воспринимал не как обычные документы, а как выполняемые сценарии. Можно также указать серверу, что все файлы с определенным расширением (например, .cgi) должны рассматриваться как CGI-сценарий. Когда пользователь открывает URL, ассоциированный с CGI-программой. клиент посылает запрос серверу, запрашивая файл. Сервер распознает, что запрошенный адрес является адресом CGI-программы, и пытается выполнить эту программу. Подробности конфигурирования Web-серверов можно найти в соответствующей литературе и документации на конкретный сервер. |
Рис 15.2. Web-страница, сформированная программой hello.cgi
HTML-формы
HTML-формы предназначены для пересылки данных от удаленного пользователя к Web-серверу. С их помощью можно организовать простейший диалог между пользователем и сервером (например, регистрацию пользователя на сервере или выбор нужного документа из представленного списка). Формы поддерживаются всеми популярными браузерами.
(Различные аспекты передачи данных Web-серверу будут рассмотрены )
Мы предполагаем, что читатель знаком с основами языка HTML и структурой HTML-документа. В этом разделе рассмотрены средства HTML, используемые для создания форм. В описании тэгов приведены только наиболее употребительные атрибуты и опущены атрибуты, специфические для отдельных браузеров.
Модуль CGI.pm
Модуль CGI.pm
Пример, рассмотренный выше, демонстрирует наивный подход, когда кажется, что все необходимые программы надо писать самостоятельно с самого начала. Но программирование CGI — это такая область, в которой Per] давно и активно применяется, и многое из того, что может потребоваться, уже давно кем-то написано. Надо только найти и использовать. В. данном разделе мы сделаем краткий обзор одного из таких готовых средств, предназначенных для поддержки разработки CGI-приложений.
Модуль CGI.pm, созданный Линкольном Штейном, входит в состав дистрибутивного комплекта Perl, начиная с версии 5.004, и его даже не нужно специально инсталлировать.
Этот модуль содержит большой набор функций для создания и обработки HTML-форм. Мы посвятили значительную часть предыдущего раздела изучению многочисленных тэгов, чтобы затем написать HTML-код для создания формы в примере 15.1. Модуль CGI позволяет сделать то же самое, но без использования HTML. С его помощью можно описать форму на языке Perl, используя вместо тэгов обращения к функциям модуля. В результате получится не документ HTML, а сценарий на языке Perl, который при вызове будет "на лету" генерировать HTML-форму и передавать серверу для отправки клиенту.
Модуль CGI является не просто модулем, а классом, что позволяет использовать преимущества объектно-ориентированного подхода. Модуль предоставляет пользователю на выбор два вида интерфейса с самим собой: процедурно-ориентированный и объектно-ориентированный.
При использовании процедурно-ориентированного способа работы с модулем CGI функции модуля нужно явным образом импортировать в пространство имен вызывающей программы, а затем обращаться к ним как обычно. В этом случае в вызывающей программе должны быть строки, аналогичные следующим:
#!/usr/bin/perl ; use CGI qw/:standard/; \ print header(), \
start_html('Пример формы'),
hi('Пример формы'),
Директива use импортирует в пространство имен вызывающей программы некоторый стандартный набор функций. Помимо него, существуют другие наборы функций модуля CGI. Их можно импортировать, указав имя соответствующего набора в списке импорта директивы use. Имена всех наборов можно просмотреть в файле CGI.pm, где они содержатся в хеш-массиве
%EXPORT_TAGS,
Функции header (), start_html О , hi () ЯВЛЯЮТСЯ функциями модуля CGI. Они будут рассмотрены ниже.
При использовании объектно-ориентированного интерфейса в директиве use вызывающей программы не нужно указывать список импортируемых имен функций. В этом случае взаимодействие с модулем CGI осуществляется через объект класса CGI, который нужно создать в вызывающей программе при помощи конструктора new (). Объектно-ориентированный вариант приведенного выше фрагмента выглядит следующим образом:
#!/usr/bin/perl
use CGI;
Squery = new CGI;
print $query->header(),
$query->start_html {'Пример формы'),
$query->hl ('Пример формы' ) ,
Замечание | |
Функции модуля CGI.pm являются методами класса CGI. Для того чтобы их можно было вызывать и как функции, и как методы, синтаксис не требует в качестве обязательного первого параметра указывать объект класса CGI. Поэтому в качестве функций к ним можно обращаться обычным образом, а как к объектам — только используя форму $object->method (). |
Будем для определенности использовать традиционный процедурно-ориентированный интерфейс. Рассмотрим следующий сценарий.
#!/usr/bin/perl
use CGI qw(:standard);
print header;
print start_html('Пример формы'),
h2('Регистрационная страница Клуба любителей фантастики'),
'Заполнив анкету, вы сможете пользоваться нашей электронной
"^библиотекой.',
br,
start_form,
"Введите регистрационное имя:",textfield('regname'),
P.
"Введите пароль: ", password_field(-name=>'passwordl',
-maxlength=>'8'),
Р,
"Подтвердите пароль: ", password_field(-name=>'password2',
-maxlength=>'8'),
Р/-
"Ваш возраст",
Р'
radio_group(-name=>'age',
-value=>['lt20','20_30', '30_50', 'gt50'],
-default=>'Lt20',
-labels=>{'It20'=>'flo 20', I 20_30'=>'20-30', 4> '30_50'=>'30-50','gt50'=>'старше 50'}),
br,br,
"На каких языках читаете:",
checkbox_group(-name=>'language', 4> -values=>
4>
['русский', 'английский' ,'французский', 'немецкий'],
^ -defaults=>['русский']), br,br,
" Какой формат данных является для Вас предпочтительным ", Ьг, popup_menu(-name=>'type',
-values=>['Plain text','PostScript','РОГ']), br,br, \
N
"Ваши любимые авторы:", x -~-_.
br,
textarea(-name=>'wish', -cols=>40, -rpws=>3),
br,
subrai t{-name=>'OK'), reset{-name=>'Отменить'),
end_form,
hr;
if (paramO) { print
"Ваше имя: ",em(param('regname')),
P,
"Ваш возраст: ", em(param('age')),
P, '
J
"Вычитаете на языках: ",em(join(", ",param('language'))),
P,
"Предпочтительный формат данных для Вас: ",em(param ('type')),
P,
"Ваши любимые авторы: ", em(join(", ",param('wish 1 ))),
hr; } print end_html;
Обсудим приведенный текст. Директива use, как мы отметили выше, осуществляет импорт стандартного набора функций модуля CGI.pm в пространство имен вызывающего пакета. В самом сценарии на месте тэгов исходного HTML-кода стоят обращения к функциям модуля: каждому тэгу соответствует вызов функции. Вызов функции модуля CGI можно осуществлять двумя способами: с использованием позиционных параметров print textfield('regname','начальное значение',50,80); с использованием именованных параметров
print textfield(-name=>'regname',
-default=>'начальное значение",
-size=>50,
-maxlength=>80);
Обработка позиционного параметра внутри функции зависит от его места в списке параметров. Обработка именованного параметра не зависит от его места в списке параметров. Функции модуля CGI могут иметь большое число параметров, порядок следования которых трудно запомнить, поэтому в этом модуле была реализована возможность вызова функций с именованными параметрами. Кроме того, применение именованных параметров делает текст программы более понятным. В тексте примера функции вызываются с именованными параметрами, если параметров больше одного. Познакомимся с функциями, использованными в примере.
Функция header о без параметров создает для виртуального ответа сервера стандартный HTTP-заголовок Content-Type: text/html и вставляет после него необходимую пустую строку. Параметры позволяют задать дополнительную информацию для заголовка, например, указать другой медиа-тип содержимого или код ответа, посылаемый браузеру:
print header(-type=>'image/gif',
-status=>'404 Not Found 1 );
Функция start_htmi () создает HTML-заголовок и начальную часть документа, включая открывающий тэг <вооу>. При помощи параметров функции можно задать дополнительные тэги внутри тэга <HEAD>, а также значения атрибутов. Все параметры являются необязательными. В примере функция start_htmio вызвана с одним позиционным параметром, определяющим название документа.
Модуль CGI содержит методы (функции) для поддержки многих тэгов HTML2, HTML3, HTML4 и расширений, используемых в браузерах Netscape. Тэгам соответствуют одноименные методы модуля CGI.pm, имена которых записываются при помощи символов нижнего регистра. Если при этом возникают конфликты имен, в названия методов следует вводить символы верхнего регистра, как, например, в следующих случаях.
1. Название тэга <TR> совпадает с именем встроенной функции tr(). Имя соответствующего метода записывать в виде TR () или тг ().
2. Название тэга <PARAM> совпадает с именем собственного метода модуля CGI paramo. Для обозначения метода, соответствующего тэгу, использовать ИМЯ РАКАМ ().
3. Название тэга <SELECT> совпадает с именем встроенной функции select (). Для обозначения метода использовать имя Select ().
4. Название тэга <зив> совпадает с именем ключевого слова объявления функции sub. Для обозначения метода использовать имя sub ().
Тэгам, имеющим атрибуты, соответствуют методы, имеющие в качестве первого аргумента ссылку на анонимный хеш-массив. Ключами этого хеш-массива являются имена атрибутов тэга, а значениями — значения атрибутов.
Методы, соответствующие тэгам, и методы, предназначенные длячгенерирова-ния других элементов HTML-документа, возвращают строки, содержащие соответствующие элементы. Чтобы эти строки попали в создаваемый документ, их нужно вывести, как это делается в примере при помощи функции print.
В примере использованы следующие методы, соответствующие тэгам HTML.
Функция Н2 соответствует тэгу <Н2>. Она определяет, что ее аргумент является в документе заголовком второго уровня.
Функция Ьг соответствует тэгу <BR> и обозначает, что последующий текст размещается с начала новой строки.
Функция р соответствует тэгу <р> и обозначает начало абзаца.
Функция hr соответствует тэгу <т> и обозначает горизонтальную линию, разделяющую документ на части.
Функция em соответствует тэгу <ет> и обозначает, что ее аргумент в документе должен быть выделен курсивом.
Следующие функции используются для создания формы и ее элементов.
Функция start_form соответствует тэгу <FORM>. Она может иметь три параметра start_form(-method=>$method,
-action=>$action,
-encoding=>$encoding);
при помощи которых можно задать метод передачи формы Web-серверу (-method), программу, предназначенную для обработки формы (-action), и способ кодирования данных (-encoding). Все параметры являются необязательными. По умолчанию используются значения
method: POST;
action: данный сценарий;
encoding: application/x-www-form-urlencoded. П Функция end_form создает закрывающий тэг </FORM>.
Функция textfieid соответствует тэгу <INPUTE TYPE=TEXT>. Она имеет следующий синтаксис
textfieid (-name=>' field__name',
-default=>'starting value',
-size=>50,
-maxlength=>80);
Параметры соответствую^ атрибутам тэга. Обязательным является первый параметр. /
х. __ _ _^/
Функция password_fieid соответствует тэгу <INPUTE TYPE=PASSWORD>. Ее синтаксис:
password_field(-name=>'secret',
-value=>'starting value',
-size=>8,
-maxlength=>12);
Параметры имеют тот же смысл, что и одноименные атрибуты соответствующего тэга. Обязательным является первый параметр.
Функция radio_group служит для создания группы "радиокнопок" — элементов, задаваемых тэгом <INPUTE TYPE=RADIO>. Ее синтаксис имеет следующую форму
radio_group(-name=>'group_name',
-values=>['bim',Jbam','bom'],
-default=>'bom',
-linebreak=>'true',
-lab.els=>\%labels) ;
Первый аргумент является обязательным, соответствует одноименному атрибуту тэга. Второй аргумент тоже обязательный и задает значения элементов. Эти значения отображаются в качестве названий кнопок. Он должен быть ссылкой на массив. Остальные аргументы являются необязательными. Третий аргумент задает кнопку, которая выбрана по умолчанию. Если значение четвертого аргумента 'true 1 , каждая следующая кнопка группы размещается в начале новой строки. Пятым аргументом является ссылка на хеш-массив, который связывает значения, присвоенные кнопкам, с метками, которые отображаются в виде названий кнопок. Если аргумент не задан, то в качестве названий отображаются сами значения.
Функция checkbox_group служит для создания группы элементов-переключателей, задаваемых тэгом <INPUTE TYPE= CHECKBOX>.
checkbox_group(-name=>'group_name',
-values=>['bim','bam','bom'],
-default=>['bim','bom'],
-linebreak=>'true',
-labels=>\%labels);
Аргументы имеют тот же смысл, что и одноименные аргументы функции radio_group. Поскольку в группе переключателей можно одновременно выбрать несколько элементов, третий аргумент может быть или одиночным элементом, или ссылкой на массив, содержащий список значений, выбранных по умолчанию. Обязательными являются первый и второй аргументы.
Функция popup_menu служит для создания меню, задаваемого при помощи тэга <SELECT>. Имеет следующий синтаксис:
popup_menu(-name=>'menu_name',
-values=>['bim', 'bam','bom'],
-default=>'bom r ,
-labels=>\%labels);
Первый аргумент задает имя меню. Второй аргумент является ссылкой на массив, содержащий список значений, присвоенных элементам меню. Первый и второй аргументы обязательны, остальные — нет. Третий аргумент задает элемент меню, выбранный по умолчанию. Четвертый 1 аргумент является ссылкой на хеш-массив. Хеш-массив значению каждого элемента меню ставит в соответствие строку, которая будет отображаться в меню для этого элемента. Если четвертый аргумент отсутствует, то для каждого элемента меню отображается его значение, заданное вторым аргументом.
Функция textarea соответствует тэгу <TEXTAREA>, задающему в документе текстовое поле для ввода многострочного текста. Имеет следующий синтаксис
textarea(-name=>'region',
-default=>'starting value',
-rows=>10,
-columns=>50);
Первый параметр, задающий имя элемента формы <ТЕХТДКЕА>, является обязательным, остальные — нет. Второй параметр задает строку, отображаемую по умолчанию. Третий и четвертый параметры задают соответственно число строк и столбцов, отображаемых в текстовом поле.
Функция submit соответствует тэгу <INPUT TYPE=SUBMIT>, задающему кнопку передачи. Ее синтаксис:
print $query->submit(-name=>'button_name', -value=>'value');
Первый параметр является необязательным. Он задает имя кнопки, которое отображается в качестве ее названия. Нужен только для переопределения названия Submit и в тех случаях, когда надо различать несколько имеющихся кнопок передачи. Второй параметр тоже необязательный. Он задает значение, которое посылается в строке запроса при щелчке на этой кнопке.
Функция reset соответствует тэгу <INPUT TYPE=RESET>, задающему кнопку сброса. Может иметь параметр, переопределяющий название Reset, отображаемое по умолчанию.
Функция end_htmi завершает HTML-документ, добавляя тэги </BODY>
</HTML>.
Пример 15.8 содержит также код, который не связан с созданием формы Он состоит из одного условного оператора, в котором в качестве условия используется значение, возвращаемое функцией paramo. Эта функция используется также внутри блока условного оператора. Разберем для чего она применяется. При помощи функции paramo модуля CGI можно выполнить следующие действия.
Получение списка имен параметров, переданных сценарию.
Если сценарию переданы параметры в виде списка пар "имя=значение" функция paramo без аргументов возвращает список имен параметров сценария:
@names = param;
Получение значений именованных параметров.
Функция paramo с единственным аргументом — именем параметра, возвращает значение этого параметра. Если параметру соответствует несколько значений, функция param о возвращает список этих значений:'
@values = param('language');
в противном случае — одно значение:
$value = param('regname');
Задание значений параметров.
param(-name => 'language', -values => ['russian', 'english', 'french']);
Можно задавать значения параметров, используя вызов функции param о в форме с позиционными параметрами, но тогда нужно знать порядок следования этих параметров:
param ('language', 'russian', 'english', 'french');
При помощи функции param о можно устанавливать начальные значения элементов формы или изменять ранее установленные значения.
Часть сценария, предшествующая условному оператору, предназначена для создания формы из примера 15.1. Заключительная часть, состоящая из условного оператора, обрабатывает заполненную и отправленную Web-серверу форму. Это происходит потому, что по умолчанию приложением, обрабатывающим форму, является данный сценарий (см. описание start__form). Таким образом, в одном сценарии содержится код, и создающий форму, и ее обрабатывающий.
Сохраним код, приведенный в примере 15.8, в файле welcome.cgi. Этот файл можно поместить на Web-сервере в стандартный каталог cgi-bin, предназначенный для хранения CGI-сценариев. Предположим, что Web-сервер имеет Internet-адрес www.klf.ru. Если из удаленного браузера послать запрос по адресу , то Web-сервер, получив запрос, выполнит сценарий welcome, cgi. Сценарий "на лету" создаст HTML-документ, содержащий форму, и передаст его Web-серверу, который отправит документ браузеру. Браузер, получив документ, отобразит его.
После заполнения формы и нажатия кнопки ОК данные формы будут вновь отправлены Web-серверу, который передаст их для обработки все тому же сценарию welcome.cgi. Сценарий "на лету" создаст новый HTML-документ с учетом полученных данных и через сервер направит его браузеру. Браузер отобразит новый документ.
Сценарий welcome.cgi можно передать для выполнения интерпретатору peri, а результат вывести в файл, чтобы посмотреть, как вызовы функций модуля CGI преобразуются в тэги HTML-документа. Документ HTML, созданный сценарием welcome.cgi, имеет следующий вид.
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> <HTMLXHEADXTITLE>npMMep <J>opMbi</TITLE> </HEADXBODY>
<Н2>Регистрационная страница Клуба любителей фантастики</Н2>
Заполнив анкету, вы сможете пользоваться нашей электронной библиотекой,
<BR>
<FORM METHOD="POST" ENCTYPE="application/x-www-form-urlencoded">
Введите регистрационное имя:<1ЫРит TYPE="text" NAME="regname" ><P>
Введите пароль: <INPUT TYPE="password" NAME="passwordl" MAXLENGTH=8><P>
Подтвердите пароль: <INPUT TYPE="password" NAME="password2" MAXLENGTH=8>
<Р>Ваш возраст<Р>
<INPUT TYPE="radio" NAME="age" VALUE="lt20" СНЕСКЕО>до 20
<INPUT TYPE="radio" NAME="age" VALUE="20_30">20-30
<INPUT TYPE="radio" NAME="age" VALUE="30_50">30-50
<INPUT TYPE="radio" NAME="age" VALUE="gt50">CTapnie 50
<BRXBR>Ha каких язьпсах читаете:
<INPUT TYPE="checkbox" NAME="language" УАШЕ="русский" СНЕСКЕП>русский
<INPUT TYPE="checkbox" NAME="language" УАШЕ="английский">английский
<INPUT TYPE="checkbox" NAME="language" УАьиЕ="французский">ф р анцузский
<INPUT TYPE="checkbox" NAME="language" VALDE="немецкий"Жемецкий
<BRXBR>
Какой формат данных является для Вас предпочтительным
<BRXSELECT NAME="type">
<OPTION VALUE="Plain text">Plain text
<OPTION VALUE="PostScript">PostScript
<OPTION VALUE="PDF">PDF
</SELECT>
<BRXBR>
Ваши любимые авторы:
<BRXTEXTAREA NAME="wish" ROWS=3 COLS=40X/TEXTAREA>
<BR>
<INPUT TYPE="sxobmit" NAME="OK" VALUE="OK">
<INPUT TYPE="reset" VALUE="Отменить">
<INPUT TYPE="hidden" NAME=".cgifields" VALUE="language">
<INPUT TYPE="hidden" NAME=".cgifields" VALUE="age">
</FORM>
<HRX/BODYX/HTML>
В действительности документ, созданный сценарием welcome. cgi, состоит из небольшого количества длинных строк, что связано с тем, как они формируются методами модуля CGI. Поэтому реально сформированный текст для удобства представлен в более структурированном виде. Но это единственное изменение, не влияющее на смысл автоматически созданного документа.
Обработка данных формы
Обработка данных формы
Данные формы поступают в CGI-программу в закодированном виде, поэтому в качестве первого шага CGI-сценарий должен выполнить декодирование полученной информации. При пересылке данных методом GET данные формы присваиваются переменной среды QUERY_STRING, при передаче методом POST — передаются в программу через стандартный ввод и тоже могут быть присвоены некоторой внутренней переменной. Таким образом, декодирование данных сводится к следующей последовательности манипуляций со строкой:
замена каждой группы %hh, состоящей из шестнадцатеричного ASCII-кода hh с префиксом %, на соответствующий ASCII-символ;
замена символов "+" пробелами;
выделение отдельных пар имя=знанение> разделенных ограничителем &;
выделение из каждой пары имя=значение имени и значения соответствующего поля формы.
Программа декодирования HTML-формы может выглядеть, например, так:
#!/usr/bin/perl
# Декодирование данных формы, переданных методом GET $form_data = $ENV{'QUERY_STRING'};
# преобразование цепочек %hh в соответствующие символы $form_data-=- s/%(..)/pack ("С", hex ($1))/eg; i преобразование плюсов в пробелы $form_data =~ tr/+/ /;
# разбиение на пары имя=значение @pairs = split (/&/, $form_data);
# выделение из каждой пары имени и значения поля формы и сохранение
# их в ассоциативном массиве $fom_fields
foreach $pair (@pairs)
{
($name, $value)=split(/=/,$pair);
$ form_fields{$name}=$value; }
Если данные формы переданы методом POST, то в приведенном тексте следует заменить оператор присваивания
$form_data = $ENV{'QUERY_STRING'};
оператором
read(STDrN,$fom_data,$ENV{'CONTENT_LENGTH' }} ;
считывающим из стандартного ввода программы CONTENT_LENGTH байтов, составляющих содержимое запроса клиента, в переменную $form_data.
В приведенном примере используются две новые функции: packQ и hex(). Поясним их назначение прежде, чем перейти к обсуждению текста программы.
Функция
pack template, list
упаковывает список значений list в двоичную структуру по заданному шаблону template. Аргумент template представляет собой последовательность символов, определяющих формат представления пакуемых данных:
а/A Текстовая строка, заполненная нулями/пробелами
b/ B Двоичная строка, значения расположены в порядке возрастания/ убывания
с/с Обычное символьное значение/ Символьное значение без знака
f/d Значение в формате с плавающей точкой одинарной/двойной точности
b/n Шестнадцатеричная строка, младший/старший полубайт первый
i/i Целое со знаком/ без знака
I/L Значение типа long со знаком/без знака
П/N Значение типа short/long с "сетевым" порядком байтов ("старший в старшем")
P/U Указатель на строку/Ш-кодированная строка s/s Значение типа short c$> знаком/без знака
v/v Значение типа short/long с VAX-порядком байтов ("старший в младшем")
х/х Нулевой байт/резервная копия байта
@ Заполнение нулевыми байтами (до абсолютной позиции)
За каждым символом может следовать число, обозначающее счетчик применений данного символа в качестве формата. Символ * в качестве счетчика означает применение данного формата для оставшейся части списка.
$х = pack "cccc", 80, .101, 114, 108; $х = pack "c4", 80, 101, 114, 108;
$х = pack "B32", "01010000011001010111001001101100";
$х = pack "H8", "5065726С";
$х = pack "H*", "5065726C"; ' •
$х = pack "сВ8Н2с",80,"01100101", 12, 108;
Значение переменной $х во всех случаях равно "peri". Функция
hex expr
Интерпретирует аргумент ехрг как шестнадцатеричную строку и возвращает ее десятичное значение.
В тексте программы примера 15.4 все представляется очевидным. Разберем только наиболее насыщенную строку
$fonn_data =~ s/%(..)/pack ("С", hex ($l))/eg;
Образец для поиска задан в виде регулярного выражения %(..). Этому образцу удовлетворяет произвольная последовательность вида %ху, где х, у — любые символы. В результате кодирования данных в качестве х, у могут появиться только шестнадцатеричные цифры, поэтому можно не задавать более точный, но менее компактный шаблон %([0-9A-Fa-f][0-9A-Fa-f]j. Часть выражения заключена в скобки (..). При нахождении подходящего фрагмента %hh его часть, содержащая шестнадцатеричное число hh, сохраняется в переменной, которая затем будет использована в качестве аргумента функции hex($ij для преобразования в десятичное значение. Функция pack упакует это десятичное значение в двоичную структуру, которая в соответствии с шаблоном "с" будет интерпретироваться как символ. Этот символ заменяет в тексте найденную цепочку %hh.
После выделения и декодирования данных можно приступить к их обработке. Попробуем написать CGI-сценарий, обрабатывающий данные формы из примера 15.1.
Основные понятия
Основные понятия
Основу "всемирной паутины" WWW составляют Web-узлы. Это компьютеры, на которых выполняется специальная программа — Web-сервер, ожидающая запроса со стороны клиента на выдачу документа. Документы сохраняются на Web-узле, как правило, в формате HTML. Клиентом Web-сервера является программа-браузер, выполняющаяся на удаленном компьютере, которая осуществляет запрос к Web-серверу, принимает запрошенный документ и отображает его на экране.
Аббревиатура CGI (Common Gateway Interface) обозначает часть Web-сервера, которая может взаимодействовать с другими программами, выполняющимися на этом же Web-узле. В этом смысле она является шлюзом (gateway — шлюз) для передачи данных, полученных от клиента, программам обработки — таким, как СУБД, электронные таблицы и др. CGI включает общую среду (набор переменных) и протоколы для взаимодействия с этими программами.
Общая схема работы CGI состоит из следующих элементов.
1. Получение Web-сервером информации от клиента-браузера. Для передачи данных Web-серверу в языке HTML имеется средство, называемое форма. Форма задается в HTML-документе при помощи тэгов <FORM>. . .</FORM> и состоит из набора полей ввода, отображаемых браузером в виде графических элементов управления: селекторных кнопок, опций, строк ввода текста, управляющих кнопок и т. д. (Рисунок 15.1).
2. Анализ и обработка полученной информации. Данные, извлеченные из HTML-формы, передаются для обработки CGI-программе. Они не всегда могут быть обработаны CGI-программой самостоятельно. Например, они могут содержать запрос к некоторой базе данных, которую CGI-программа читать "не умеет". В этом случае CGI-программа на основании полученной информации формирует запрос к компетентной программе, выполняющейся на том же компьютере. CGI-программа может быть написана на любом языке программирования, имеющем средства обмена данными между программами. В среде UNIX для этой цели наиболее часто используется язык Perl. Так как UNIX является наиболее популяр-
ной операционной системой для Web-серверов, то можно считать Perl наиболее популярным языком CGI-программирования. Программа на языке Perl представляет собой последовательность операторов, которые интерпретатор языка выполняет при каждом запуске без преобразования исходного текста программы в выполняемый двоичный код. По этой причине CGI-программы называют также CGI-сценариями или CGI-скрип-тами.
Создание нового HTML-документа и пересылка его браузеру. После обработки полученной информации CGI-программа создает динамический или, как говорят, виртуальный HTML-документ, или формирует ссылку на уже существующий документ и передает результат браузеру.
Рис 15.1. Пример отображения HTML-формы браузером
Передача информации CGI-программе
Передача информации CGI-программе
Как мы уже знаем, существуют два метода кодирования информации, содержащейся в форме: стандартный метод application/x-www-form-urlencoded, используемый по умолчанию, и дополнительный multipart/form-data. Второй метод нужен только в том случае, если к содержимому формы присоединяется локальный файл, выбранный при помощи элемента формы < INPUT TYPE=FILE>. В остальных случаях следует использовать метод кодирования по умолчанию.
Схема кодирования application/x-www-form-urlencoded одинакова для обоих методов пересылки GET и POST и заключается в следующем.
Для каждого элемента формы, имеющего имя, заданное атрибутом МИМЕ, формируется пара "name=value", где value — значение элемента, введенное пользователем или назначенное по умолчанию. Если значение отсутствует, соответствующая пара имеет вид "пате—'. Для радиокнопок и переключателей используются значения только выбранных элементов. Если элемент выбран, а значение атрибута VALUE не определено, по умолчанию используется значение "ON".
Все пары объединяются в строку, в качестве разделителя служит символ &. Так как имена и значения представляют собой обычный текст, то они могут содержать символы, недопустимые в составе URL (метод GET пересылает данные как часть URL). Такие символы заменяются последовательностью, состоящей из символа % и их шестнадцатеричного ASCII-кода. Символ пробела может заменяться не только кодом %20, но и знаком + (плюс). Признак конца строки, встречающийся в поле TEXTAREA, заменяется кодом %OD%OA. Такое кодирование называется URL-кодированием.
Закодированная информация пересылается серверу одним из методов GET или POST. Основное отличие заключается в том, как метод передает информацию CGI-программе.
При использовании метода GET данные формы пересылаются серверу в составе URL запроса, к которому добавляются после символа ? (вспомним, что запрос — это формализованный способ обращения браузера к Web-серверу). Тело запроса в этом случае является пустым. Для формы из примера 15.1 запрос выглядит следующим образом:
GET /cgi-bin/registrar.cgi? regname = bobSpasswordl = rumataSpassword2 = rumata&age = lt20&language = russian&format = HTML&wish = %F6%C5%CC%Dl%DA%CE%D9 HTTP/1.0
( заголовки запроса, сообщающие серверу, информацию о клиенте) <пусто> (тело запроса). Часть URL после символа "?" называется строкой запроса. Web-сервер, получив запрос, присвоит переменной среды QUERY_STRING значение строки запроса и вызовет CGI-программу, обозначенную в первой части URL до символа "?": /cgi-bin/registrar.cgi. CGI-Программа registrar.cgi сможет затем обратиться к переменной QUERY_STRING для обработки закодированных в ней данных.
Обратите внимание на то, что данные, введенные в поле типа PASSWORD, передаются открытым текстом без шифрования. При передаче данных методом GET они в составе URL помещаются в файл регистрации доступа access.log, обычно открытый для чтения всем пользователям. Таким образом "секретные" данные, введенные в поле типа PASSWORD, оказываются доступными посторонним.
Замечание |
|
Метод GET позволяет передавать данные CGI-программе вообще без использования форм. Информацию, содержащуюся в приведенном выше URL, можно передать при помощи следующей гиперссылки, помещенной в HTML-документ: <А HREF=" 4>bobspasswordl=rumata&password2=rimata&age=lt20slanguage=russian& 4>format=HTML&wish=%F6%C5%CC%Dl%DA%CE%D9 ">СС1-программа</А>, заменив в этом фрагменте символ "&" его символьным примитивом & или & для правильной интерпретации браузером. |
Строка запроса — не единственный способ передачи данных через URL. Другим способом является дополнительная информация о пути (extra path information), представляющая собой часть URL, расположенную после имени CGt-программы. Сервер выделяет эту часть и сохраняет ее в переменной среды PATH_INFO. CGI-программа может затем использовать эту переменную для извлечения данных. Например, URL
4>regname = bobspasswordl = rumataspassword2 = r\amata&age = lt20&language = 4>russian&format = HTML&wish = %F6%C5%CC%Dl%DA%CE%D9
содержит уже знакомые нам данные, но не в виде строки запроса, а в виде дополнительной информации о пути. При получении запроса с таким URL сервер сохранит данные в переменной среды
PATH_INFO = /regname = bobspasswordl = rumataspassword2 = rumata&age = l blt20&language = russian&format = HTML&wish = %F6%C5%CC%Dl%DA%CE%D9"
Название объясняется тем, что обычно этим способом передается информация о местоположении какого-либо файла (extra path information). Например, URL
содержит дополнительную информацию PATH_iNFO=/texts/jdk_doc.txt" о местонахождении файла jdk_doc.txt относительно корневого каталога дерева документов. Другая переменная среды PATHJTRANSLATED содержит информацию об абсолютном местоположении файла в файловой системе, например,
PATH_TRANSLATED="/hcme/httpd/docs/texts/jdk_doc.txt"
а переменная DOCUMENT_ROOT содержит путь к корневому каталогу дерева документов, В нашем случае DOCUMENT_ROOT="/home/httpd/docs/".
При использовании метода POST данные формы пересылаются серверу в теле запроса. Если в примере 15.1 вместо метода GET использовать метод POST
<form method="post" action="/cgi-bin/registrar.cgi">,
то запрос клиента будет иметь следующий вид:
POST /cgi-bin/registrar.cgi HTTP/1.1
(заголовки запроса, сообщающие серверу информацию о клиенте)
Content-length: 126
regname=bob&passwordl=rumata&password2=ruinata&age=lt20&language=russian& 4>format=HTML&wish=%F6%C5%CC%Dl%DA%CE%D9
В этом фрагменте среди прочих заголовков выделен заголовок content-length, сообщающий серверу количество байт, переданных в теле запроса. Это значение сервер присваивает переменной среды CONTENT_LENGTH, а данные посылает в стандартный ввод CGI-программы.
Методы GET и POST имеют свои достоинства и недостатки. Метод GET обеспечивает лучшую производительность при пересылке форм, состоящих из небольшого набора коротких полей. При пересылке большого объема данных следует использовать метод POST, так как браузер или сервер могут накладывать ограничения на размер данных, передаваемых в составе URL, и отбрасывать часть данных, выходящую за границу. Метод POST, к тому же, является более надежным при пересылке конфиденциальной информации.
Переменные среды CGI
Переменные среды CGI
В зависимости от метода данные формы передаются в CGI-программу или через стандартный ввод (POST), или через переменную среды QUERY_STRING (GET). Помимо этих данных CGI-программе доступна и другая информация, поступившая от клиента в заголовках запроса или предоставленная Web-сервером. Эта информация сохраняется в переменных среды UNIX. С некоторыми из них мы уже познакомились ранее. В табл. 15.1 перечислены переменные, обычно используемые в CGI.
Таблица 15.1. Переменные среды CGI
Переменная среды |
Описание | ||
GATEWAYJNTERFACE |
Версия CGI, которую использует сервер | ||
SERVER_NAME |
Доменное имя или IP-адрес сервера | ||
SERVER_SOFTWARE |
Имя и версия программы-сервера, отвечающей на запрос клиента (например, Apache 1 .3) | ||
SERVER_PROTOCOL |
Имя и версия информационного протокола, который был использован для запроса (например, HTTP 1 .0) | ||
SERVER_PORT |
Номер порта компьютера, на котором работает сервер (по умолчанию 80) | ||
REQUEST_METHOD |
Метод, использованный для выдачи запроса (GET, POST) | ||
PATHJNFO |
Дополнительная информация о пути | ||
PATHJRANSLATED |
Та же информация, что и в переменной PATHJNFO с префиксом, задающим путь к корневому каталогу дерева Web-документов | ||
SCRIPT_NAME |
Относительное маршрутное имя CGI-сценария (например, /cgi-bin/program.pl) | ||
DOCUMENT_ROOT |
Корневой каталог дерева Web-документов | ||
QUERY_STRING |
Строка запроса— информация, переданная в составе URi запроса после символа "?" | ||
REMOTE_HOST |
Имя удаленной машины, с которой сделан запрос | ||
REMOTE_ADDR |
IP-адрес удаленной машины, с которой сделан запрос | ||
REMOTE_USER |
Идентификационное имя пользователя, посылающего запрос | ||
CONTENT_TYPE |
Медиа-тип данных запроса, например, "text/html". | ||
CONTENT_LENGTH |
Количество байт в теле запроса, переданных в CGI-программу через стандартный ввод | ||
HTTP_HOST |
Хост-имя компьютера, на котором работает сервер | ||
HTTP_FROM |
Адрес электронной почты пользователя, направившего запрос | ||
HTTP_ACCEPT |
Список медиа-типов, которые может принимать клиент | ||
HTTP_USER_AQENT |
Браузер, которым клиент пользуется для выдачи запроса | ||
HTTP_REFERER |
URL документа, на который клиент указывал перед обращением к CGI-программе |
Имена переменных среды CGI на разных Web-серверах могут различаться. Следует обратиться к документации на соответствующий сервер.
CGI-программа на языке Peri имеет доступ к переменным среды через специальный предопределенный хеш-массив %ENV, к элементам которого можно обратиться по ключу, совпадающему с именем переменной среды. Ниже приведены пример CGI-сценария, формирующего HTML-документ с информацией о всех установленных переменных среды, и отображение этого документа в окне браузера.
#!/usr/bin/perl
print "Content-type:text/html\n\n";
print "<html>\n";
print "<head><title>Преременные cpeды</titlex/head>\n";
print "<bоdу><h2>Переменные среды</h2>\n";
print "<hrxpre>\n";
foreach $name (sort(keys %ENV))
{
print "$name: $ENV($name}\n";
}
print "<hrx/pre>\n";
print "</bodyx/html>\n";
Рис 15.3. Информация о переменных среды CGI
Пример создания собственного CGI-сценария
Пример создания собственного CGI-сценария
Программа должна декодировать полученные данные, проверять заполнение обязательных полей формы и правильность подтверждения пароля, в зависимости от результатов проверки формировать документ для отсылки клиенту. Сохраним сценарий в файле /cgi-bin/registrar, cgi. Полный маршрут к данному файлу определяется параметрами конфигурации Web-сервера. Местоположение каталога cgi-bin обычно указывается относительно корня дерева документов Web-сервера, а не корневого каталога файловой системы. Например, если корнем является каталог /home/httpd/htmi/, то файл сценария будет иметь маршрутное ИМЯ /home/httpd/html/cgi-bin
/registrar.cgi, которое в запросе клиента будет указано как /cgi-bin /registrar.cgi. В первом приближении текст сценария может выглядеть следующим образом.
#!/usr/bin/perl
print "Content-type:text/html\n\n"; $method = $ENV{'REQUEST_METHOD'}; if ($method eq "GET") { ^
$form_data = $ENV{'QUERY_STRING'}; } else {
read (STDIN, $form_data, $ENV{'CONTENT_LENGTH'}); }
$form_data =~ s/%(..)/pack ("C", hex ($l))/eg; $form_data =~ tr/+/ /; @pairs = split (/&/, $form_data); foreach $pair (Spairs) {
($name, $value)=split(/=/,$pair);
$FORM{$name}=$value;
Проверка заполнения обязательных полей
if (!$FORM{'regname'} I I !$FORM{'passwordl'}) { print «goback
<html>
<head><title>Невведенные данные </title></head>
<body><h2>Извините, Вы пропустили обязательные данные</п2>
<br>
<а href=" ">Попробуйте еше раз, пожалуйста</а>
</body>
</html> goback ;}
#Проверка правильности ввода пароля elsif ($FORM{'passwordl 1 } eq $FORM{'password2'}){ print«confirmation <htrml>
<head><title>no3flpaBnHeM!</titlex/head> <Ьойу><h2>Поздравляем! </h2><br>
Ваша регистрация прошла успешно. Вы можете пользоваться нашей библиотекой. Спасибо за внимание.
</body>
Рис 15.5. Подтверждение регистрации
В противном случае формируется HTML-документ, предлагающий ввести пароль повторно (Рисунок 15.6). Этот новый документ содержит форму, в состав которой входят два видимых поля типа "password" — для ввода и подтверждения пароля, и скрытые поля типа "hidden" — для сохранения остальных данных, введенных при заполнении исходной формы. Каждое скрытое поле новой формы наследует у соответствующего поля исходной формы атрибуты name и value. Если эти данные не сохранить, то их придется вводить заново, принуждая пользователя повторно выполнять уже сделанную работу. Информация, сохраненная в скрытых полях, невидима пользователю и недоступна для изменения.
Рис 15.6. Повторное приглашение для ввода пароля
Культура Perl допускает различные уровни владения языком. В рассмотренном варианте использован минимальный набор средств. Очевидно, что часть кода, например, декодирование, требуется при обработке не только данной, но и любой другой формы. Естественным шагом в развитии исходного варианта сценария является выделение этой части в отдельную подпрограмму и предоставление доступа к ней другим сценариям. Для этого преобразуем исходный текст в соответствии с планом, изложенным в примере 15.7.
1. Часть исходного кода может быть использована другими CGI-программами. Преобразуем ее в отдельный модуль, сохраняемый в файле CGI__UTILS.pm.
package CGI_UTILS; require Exporter;
@ISA = qw(Exporter);
^EXPORT = qw(print_header process_input);
# Подпрограмма вывода заголовка ответа sub print_header {
print "Content-type: text/html\n\n"; } .
# Подпрограмма декодирования данных форьы sub process_input {
my ($form_ref)=(?_.;
my ($ form_data,@pai rs);
my ($temp)="";
if ($ENV{'REQUEST_METHOD'} eq 'POST') {
read(STDIN,$form_data,$ENV{'CONTENT_LENGTH'}); } else {
$form_data=$ENV{'QUERY_STRING'}; }
$form_data=~s/%(..)/pack("c",hex($1))/ge; $form_data=~tr/+/ /; $form_data=~s/\n/\0/g; @pairs=split(/&/,$form_data); foreach $item(@pairs) {
($name,$value)=spl£t (/=/,$item) ; if (!defined($forih_ref->{$name})) <
$ form_ref->{Sname}=$value; } else {
$form_ref->{$name} .= "\0$value"; } }
foreach $item (sort keys %$form_ref) { $temp.=$item."=".$form_ref->{$item}."&";} return($temp); } 1;
2. Текст основного сценария обработки формы registrar.cgi преобразуем следующим образом:
#!/usr/bin/perl use cgi_utils;
my 8FORM, $file_rec; $file_rec=&process_input(\%FORM); ^Проверка заполнения обязательных полей
#if {$FORM{'regname'} eq "" $FORM{'passwordl'} eq "") { if (!$FORM{'regname'} !$FORMTpasswordl'}) {
print "Location: /goback.html\n\n"; }
#Проверка правильности ввода пароля
elsif ($FORM{'passwordl'} eq $FORM{'password2'}}{
print "Location: /confirmation.html\n\n";
open (OUTF, "»users");
print OUTF $file_rec, H \n";
close OUTF }
else {
&print_header; print«new_form
<html>
<head><title>Ошибка при вводе пароля</titlex/head>
<ЬойухпЗ>Введенные Вами значения пароля не совпадают
<br><forro method="get" action="/cgi-bin/registrar.cgi">
<pre>
Введите пароль: <input type="password" name="passwordl">
Подтвердите пароль: <input type="password" name="password2">
</pre> new_form / foreach $key ( keys %FORM) {
if ($key ne "passwordl" && $key ne "password2") {
print "<input type=\"hidden\' J name=$key value=$FORM{$key}>\n";
} } print«EndOfHTML
<br><br>
<input type="submit" value="OK">
<input type="reset" value="Отменить">
</form>
</body>
</html> EndOfHTML
} exit
3. В исходном варианте сценария в качестве ответов сервера при получении неполных данных и для подтверждения регистрации пользователя формируются виртуальные HTML-документы. В этом нет необходимости, так как они содержат только статическую информацию. Соответствующие фрагменты сценария преобразуем в HTML-код ротовых документов, которые сохраним в отдельных файлах. В основном сценарии в качестве ответа сервера возвращаются ссылки на эти документы.
Файл confirmation. html содержит документ, посылаемый клиенту в качестве сообщения об успешной регистрации:
<html>
<head><title>Пoздpaвляeм!</title></head> <body><h2>Пoздpaвляeм! </h2><br>
Ваша регистрация прошла успешно. Вы можете пользоваться нашей библиотекой. ..- -
<br>
Спасибо за внимание.
</body>
</html>
Файл goback.html содержит документ, посылаемый клиенту при получении неполных данных:
<html>
<head><title>Heпoлныe данные</^^1ех/пеай>
<body><h2>HsBHHMTe, Вы пропустили обязательные данные</h2>
<br>
<а href=" ">Попробуйте еще раз, пожалуйста </а>
</body>
</htral>
В приведенном тексте появились некоторые новые элементы, которые необходимо пояснить.
Подпрограмма process_input модуля cgi_utiis.pm передает декодированные данные через вызываемый по ссылке параметр — ассоциативный массив. [Кроме того, она возвращает при помощи функции return () те же данные, но в виде строки, состоящей из пар имя=значение, разделенных символом "&". Обратите внимание на то, как подпрограмма вызывается в основной программе:
$file_rec=sprocess_input(\%FORM);
В качестве аргумента ей передается ссылка на ассоциативный массив. В тексте подпрограммы появилась проверка наличия полей формы с совпадающими именами и разными значениями:
if (!defined($form_ref->{$name})) {
$form_ref->{$name}=$value; }
else { }}
Этот фрагмент необходим для того, чтобы правильно обработать следующую ситуацию из нашего примера. Выбраны несколько переключателей, определяющих языки, которыми владеет пользователь: русский, английский, французский. Так как соответствующие элементы формы имеют одинаковые имена name=language, то без проверки в ассоциативный массив %fcrm_ref, куда помещаются обработанные данные, попадет только информация от последнего обработанного Элемента name=language value=french. В Подобном случае обычное присваивание заменяется операцией присваивания с конкатенацией
$form_ref->{$name} .= "\0$value",
которая к переменной $fom_ref->{$name) добавляет нулевой символ и значение $value.
В основной программе registrar.cgi обратим внимание на то, как передается ссылка на готовый HTML-документ. Для этого вместо заголовка content-type: text/html выводится заголовок Location: URL, сообщающий серверу адрес документа.
Еще один новый элемент в основной программе — сохранение данных в файле с именем users.
Тэг <FORM>
Тэг <FORM>
<FORM ACTION="URL" МЕТНОО=метод_передачи ЕНСТУРЕ=М1МЕ-!гип>
содержание_формы
</FORM>
В HTML-документе для задания формы используются тэги <FORM>. . .</FORM>, отмечающие, соответственно, начало и конец формы. Документ может содержать несколько форм, но они не могут быть вложены одна в другую. Тэг <FORM> имеет атрибуты ACTION, METHOD и ENCTYPE. Отдельные браузеры (Netscape, Internet Explorer) поддерживают дополнительные атрибуты помимо стандартных, например, CLASS, NAME, STYLE и др.
Атрибут ACTION — единственный обязательный. Его значением является адрес (URL) CGI-программы, которая будет обрабатывать информацию, извлеченную из данной формы.
Атрибут METHOD определяет метод пересылки данйых, содержащихся в форме, от браузера к Web-серверу. Он может принимать два значения; GET (по умолчанию) и POST.
Замечание | ||
Взаимодействие между клиентом-браузером и Web-сервером осуществляется по правилам, заданным протоколом HTTP, и состоит из запросов клиента и ответов сервера. Запрос разбивается на три части. В первой строке запроса содержится HTTP-команда, называемая методом, URL запрашиваемого файла и номер версии протокола HTTP. Вторая часть— заголовок запроса. Третья часть — тело запроса, собственно данные, посылаемые серверу. Метод сообщает серверу о цели запроса. В протоколе HTTP определены несколько методов. Для передачи данных формы в CGI-программу используются два метода: GET И POST. |
При использовании метода GET данные формы пересылаются в составе URL запроса, к которому присоединяются после символа "?" в виде совокупности пар переменная=значение, разделенных символом "&". В этом случае первая строка запроса может иметь следующий вид:
После выделения данных из URL сервер присваивает их переменной среды QUERY_STRING, которая может быть использована CGI-программой.
При использовании метода POST данные формы пересылаются Web-серверу в теле запроса, после чего передаются сервером в CGI-программу через стандартный ввод.
Значением атрибута ENCTYPE является медиа-тип, определяющий формат кодирования данных при передаче их от браузера к серверу. Браузер кодирует данные, чтобы избежать их искажения в процессе передачи. Возможны два значения этого атрибута: appiication/x-wuw-form-uriencoded, используемое ПО умолчанию, И multipart/form-data.
Замечание | |
Одним из первых применений Internet была электронная почта, ориентированная на пересылку текстовых сообщений. Часто возникает необходимость вместе с текстом переслать данные в нетекстовом формате, например, упакованный zip-файл, рисунок в формате GIF, JPEG и т. д. Для того чтобы пересылать средствами электронной почты такие файлы без искажения, они кодируются в соответствии с некоторым стандартом. Стандарт MIME (Multipurpose Internet Mail Extensions, многоцелевые расширения электронной почты для Internet) определяет набор MIME-типов, соответствующих различным типам данных, и правила их пересылки по электронной почте. Для обозначения MIME-типа используется запись вида тип/подтип. Тип определяет общий тип данных, например, text, image, application (тип application обозначает специфический внутренний формат данных, используемый некоторой программой), а подтип — конкретный формат внутри типа данных, например, application/zip, image/gif, text/html. MIME-типы нашли применение в Web, где они называются также ме-dua-типами, для идентификации формата документов, передаваемых по протоколу HTTP. В HTML-форме атрибут ENCTYPE определяет медиа-тип, который используется для кодирования и пересылки специального типа данных — содержимого формы. |
<INPUT>, <SELECT>, <TEXTAREA>, которые могут употребляться только внутри
тэга <FORM>.
Тэг <INPUT>
Тэг <INPUT>
<INPUT ТУРЕ=тип_лоля_ввода ЫАМЕ=имя_лоля_ввода другие_атрибуты>
Наиболее употребительный тэг, с помощью которого можно генерировать внутри формы поля для ввода строки текста, пароля, имени файла, различные кнопки. Он имеет два обязательных атрибута: TYPE и NAME. Атрибут TYPE определяет тип поля: селекторная кнопка, кнопка передачи и др. Атрибут NAME определяет имя, присваиваемое полю. Оно не отображается браузером, а используется в качестве идентификатора значения, передаваемого Web-серверу. Остальные атрибуты меняются в зависимости от тира поля. Ниже приведено описание типов полей, создаваемых при помощи тэга <INPUT>, и порождаемых ими элементов ввода.
TYPE=TEXT Создает элемент для ввода строки текста. Дополнительные атрибуты:
MAXLENGTH=n Задает максимальное количество символов, разрешенных в текстовом поле. По умолчанию не ограничено,
SIZE=n Максимальное количество отображаемых символов.
УАЫ1Е=начальное_значение
Первоначальное значение текстового поля.
TYPE=PASSWORD
Создает элемент ввода строки текста, отличающийся от предыдущего только тем, что все вводимые символы представляются в виде символа *.
Замечание | ||
Поле PASSWORD не обеспечивает безопасности введенного текста, так KaKjna сервер он передается в незашифрованном виде. /-"'" |
TYPE=FILE
Создает поле для ввода имени локального файла, сопровождаемое кнопкой Browse. Выбранный файл присоединяется к содержимому формы при пересылке на сервер. Имя файла можно ввести непосредственно, или, воспользовавшись кнопкой Browse, выбрать его из диалогового окна, отображающего список локальных файлов. Для корректной передачи присоединенного файла следует установить значения атрибутов формы равными ENCTYPE="multipart/form-data" И METHOD=POST. В Противном случае будет передана введенная строка, то есть маршрутное имя файла, а не его содержимое. Дополнительные атрибуты MAXLENGTH и SIZE имеют тот же смысл, что и для элементов типа TEXT и PASSWORD.
TYPE=CHECKBOX Создает элемент-переключатель, принимающий всего два значения (on/off, вкл./выкл., истина/ложь) и отображаемый в виде квадратной кнопки. Элементы-переключатели CHECKBOX можно объединить в группу, установив одинаковое значение атрибута NAME для всех ее элементов. Дополнительные атрибуты:
УАШЕ= строка Значение, которое будет передано серверу, если данная кнопка выбрана. Если кнопка не выбрана, значение не передается. Обязательный атрибут.
CHECKED Если указан атрибут CHECKED, элемент является выбранным по умолчанию.
Если переключатели образуют группу, то передаваемым значением является строка разделенных запятыми значений атрибута VALUE всех выбранных элементов.
TYPE=RADIO Создает элемент "радиокнопка", существующий только в составе группы подобных элементов, из которых может быть выбран только один. Все элементы группы должны иметь одинаковое значение атрибута NAME. Отображается в виде круглой кнопки. Дополнительные атрибуты:
VALUE=Cтpoкa Обязательный атрибут, значение которого передается серверу при выборе данной кнопки. Должен иметь уникальное значение для каждого члена группы.
CHECKED Устанавливает элемент выбранным по умолчанию. Один и только один элемент в группе должен иметь этот атрибут.
TYPE=SUBMIT Создает кнопку передачи, нажатие которой вызывает пересылку на сервер всего содержимого формы. По умолчанию отображается в виде прямоугольной кнопки с надписью Submit. Дополнительный атрибут
УАШЕ=яазвание_кнолки позволяет изменить надпись на кнопке. Атрибут NAME для данного элемента может быть опущен. В этом случае значение кнопки не включается в список параметров формы и не передается на сервер. Если атрибуты
NAME И VALUE Присутствуют, Например,
<INPUT TYPE=SUBMIT NAME="submit_button" VALUE="OK">,
то в список параметров формы, передаваемых на сервер, включается параметр submit_button="OK". Внутри формы могут существовать несколько кнопок передачи.
TYPE=RESET Создает кнопку сброса, нажатие которой отменяет все сделанные изменения, восстанавливая значения полей формы на тот момент, когда она была загружена. По умолчанию отображается в виде прямоугольной кнопки с надписью Reset. Надпись можно изменить при помощи дополнительного атрибута
ЧКШЕ.=название_кнопки Значение кнопки Reset никогда не пересылается на сервер, поэтому у нее отсутствует атрибут NAME.
TYPE=IMAGE Создает элемент в виде графического изображения, действующий аналогично кнопке Submit. Дополнительные атрибуты:
ЗКС=иг!_изображения Задает ссылку (url) на файл с графическим изображением элемента.
КЬТ.СП=тип_въ1равнивания Задает тип выравнивания изображения относительно текущей строки текста точно так же, как одноименный атрибут тэга <IMG>.
Если на изображении элемента щелкнуть мышью, то координаты указателя мыши в виде NAME.x=n&NAME.y=m включаются браузером в список параметров формы, посылаемых на сервер.
TYPE=HIDDEN Создает скрытый элемент, не отображаемый пользователю. Информация, хранящаяся в скрытом поле, всегда пересылается на сервер и не может быть изменена ни пользователем, ни браузером. Скрытое поле можно использовать, например, в следующем случае. Пользователь заполняет форму и отправляет ее серверу. Сервер посылает пользователю для заполнения вторую форму, которая частично использует информацию, содержащуюся в первой форме. Сервер не хранит историю диалога с пользователем. Он обрабатывает каждый запрос независимо и при получении второй формы не будет знать, как она связана с первой. Чтобы повторно не вводить уже введенную информацию, можно заставить CGI-програм-му, обрабатывающую первую форму, переносить необходимые данные в скрытые поля второй формы. Они не будут видимы пользователем и, в то же время, доступны серверу. Значение скрытого поля определяется атрибутом VALUE.
Тэг <SELECT>
<SELECT NAME=HM*_n<afl# SIZE=n MULTIPLE>
элементы OPTION </SELECT>
Тэг <SELECT> предназначен для того, чтобы организовать внутри формы выбор из нескольких вариантов без применения элементов ввода типа CHECKBOX и RADIO. Дело в том, что если элементов выбора много, то представление их в виде переключателей и радиокнопок увеличивает размеры формы, делая ее труднообозримой. С помощью тэга <SELECT> варианты выбора более компактно представляются в окне браузера в виде элементов ниспадающего меню или списка прокрутки. Тэг имеет следующие атрибуты.
NAME= строка Обязательный атрибут. При выборе одного или нескольких элементов формируется список выбранных значений, который передается на сервер под именем NAME.
SIZE=n Устанавливает число одновременно видимых элементов выбора. Если п=1, то отображается ниспадающее менй, если п>1, то список прокрутки с п одновременно видимыми элементами.
MULTIPLE Означает, что из меню или списка можно выбрать одновременно несколько элементов. Если этот атрибут задан, то список выбора ведет себя как группа переключателей CHECKBOX, если не задан — как группа радиокнопок RADIO.
Элементы меню задаются внутри тэга <SELECT> при помощи тэга <OPTION>:
<OPTION SELECTED УАШЕ=строка>содержимое_тэга</ОРТION>
Закрывающий тэг </OPTION> не используется. Атрибут VALUE содержит значение, которое пересылается серверу, если данный элемент выбран из меню или списка. Если значение этого атрибута не задано, то по умолчанию оно устанавливается равным содержимому тэга <OPTION>. Например, элементы
<OPTION VALUE=Red>Red <OPTION>Red
имеют одно значение Red. В первом случае оно установлено явно при помощи атрибута VALUE, во втором — по умолчанию. Атрибут SELECTED изначально отображает элемент как выбранный.
Тэг <TEXTAREA>
<TEXTAREA НАМЕ=имя ROWS=m COLS=n>
текст
</TEXTAREA>
Создает внутри формы поле для ввода многострочного текста, отображаемое в окне браузера в виде прямоугольной области с горизонтальной и вертикальной полосами прокрутки. Для пересылки на сервер каждая введенная строка дополняется символами %OD%OA (ASCII-символы "Возврат каретки" и "Перевод строки" с предшествующим символом %), полученные строки объединяются в одну строку, которая и отправляется на сервер под именем, задаваемым атрибутом NAME. Атрибуты:
NAME ' __ Необходимый атрибут, используемый для идентификации данных при пересылке на сервер.
COLS=n Задает число столбцов видимого текста.
ROWS=n Задает число строк видимого текста.
Между тэгами <textarea> и </textarea> можно поместить текст, который будет отображаться по умолчанию.
Пример формы
Ниже представлен пример формы, включающей набор характерных полей и HTML-код, использованный для ее создания.
<htmlxheadxtitle>пpимep формы</^д^1ех/пеаЗ>
<body>
<b2>Регистрационная страница Клуба любителей фантастики</b2>
Заполнив анкету, вы сможете пользоваться нашей электронной библиотекой.
<br>
<form method="get" action="/cgi-bin/registrar.cgi">
<pre>
Введите регистрационное имя: <input type="text" name="regnarae">
Введите пароль: <input type="password" name="passwordl" max-length=8>
Подтвердите пароль: <input type="password" name="password2" max-length=8>
</pre>
Ваш возраст:
<input type="radio" name="age" value="lt20" checked >До 20
<input type="radio" name="age" value="20_30">20-30
<input type="radio" name="age" value="30_50">30-50
<input type="radio" name="age" value="gt50">CTapiue 50
<brxbr>
На каких языках читаете:
<input type="checkbox" name="language" value="russian" checked>pycciorii
<input type="checkbox" name="language" ^а1ие="english">английский
<input type="checkbox" name="language" Уа1ие="£гепсЬ">французский
<input type="checkbox" name="language" value="germnan">немецкий
<brxbr>
Какой формат данных является для Вас предпочтительным
<br>
<select name="format" size=2 >
<option selected value="HTML">HTML
<option value="Plain text">Plain text
<option value="PostScript">PostScript
<option value="PDF">PDF </select> <brxbr>
Ваши любимые авторы: <br> <textarea name="wish" cols=40 rows=3>
</textarea> <brxbr>
<input type="submit" value="OK"> <input type="reset" уа!ие="0тменить">
</form>
</body> \
</html>
Данная форма содержит:
текстовое поле для ввода регистрационного имени пользователя;
текстовое поле для ввода пароля, отображаемого в окне символами *;
текстовое поле для подтверждения пароля, также отображаемого символами *;
группу радиокнопок для указания возраста пользователя (единственный выбор);
группу переключателей для указания языков, которыми владеет пользователь (множественный выбор);
список прокрутки для указания предпочтительного формата данных (выбор из ограниченного списка);
блок ввода многострочного текста для перечисления любимых авторов (неизвестное заранее количество строк);
кнопку передачи с меткой ОК (у этого элемента отсутствует атрибут NAME, он не нужен, так как в данном примере всего одна кнопка передачи, а, значит, CGI-программе нет необходимости определять, от какой именно кнопки поступила команда передачи данных);
кнопку сброса с меткой Отменить.
Итак, пользователь заполнил форму и щелкнул кнопку передачи Submit. Дальнейшее прохождение данных выглядит следующим образом.
1. Информация кодируется и пересылается на Web-сервер, который передает ее для обработки CGI-программе.
2. CGI-программа обрабатывает полученные данные, возможно, обращаясь за помощью к другим программам, выполняющимся на том же компьютере, и генерирует новый "виртуальный" HTML-документ, либо определяет ссылку на уже имеющийся.
3. Новый HTML-документ или ссылка передаются CGI-Программой Web-серверу для возврата клиенту.
Рассмотрим эти шаги более подробно.
Используя модуль CGI, дополните пример
Упражнения
1. Запишите текст примера 15.8 в обозначениях, использующих объектно-ориентированный интерфейс с модулем CGI.
2. Используя модуль CGI, дополните пример 15.8 кодом, осуществляющим проверку введенных данных, как это сделано в примере 15.76.
3. Ниже приведены тексты трех примеров, входящих в отдельный дистрибутив модуля CGI.pm. Разберите, что делают эти сценарии.
a) clickable_image.cgi
#!/usr/bin/perl
use CGI;
$query = new CGI;
print $query->header;
print $query->start__html("A Clickable Image");
print «END;
<H1>A Clickable Image</H1>
</A> /
END |
print "Sorry, this isn't very exciting!\n";
print $query->startform;
print $query->image_button('picture',"./wilogo.gif"); print "Give me a: ", $query->popup_rnenu ('letter',
['A', 'B', 'C', 'D', 'E', 'W]),"\n"; print "<P>Magnification: ", $query->radio_group('magnification',
['IX' ,'2X',MX','20X']),"\n"; print "<HR>\n"; if ($query->param) {
print "<P>Magnification, <EM>",$query->param('magnification'),
"</EM>\n";
print "<P>Selected Letter, <EM>",$query->param( 'letter'),"</EM>\n"; ($x,$y) = ($query->param('picture.x'),$query->param('picture.y')) ; print "<P>Selected Position <EM>($x,$y)</EM>\n";
}
print $query->end_html;
6) quadraphobia.cgi #!/usr/bin/perl use CGI qw/:standard/; print header,
start_html('QuadraPhobia'),
hi('QuadraPhobia'),
start_form(),
image_button(-name=>'square',
-src=>'red_square.gif,
-width=>200,
-height=>200,
-align=>MIDDLE),
end_form(); if (paramO) {
($x,$y) = (param('square.x'),param('square.у'));
$pos = 'top-left' if $x < 100 && $y < 100;
$pos = 'top-right' if $x >= 100 && $y < 100;
$pos = 'bottom-left' if $x < 100 && $y >= 100;
$pos = 'bottom-right' if $x >= 100 && $y >= 100;
print b(" You clicked on the $pos part of the square."); }
print p,a({href=>'../source.html'},"Code examples"); print end_html ();
в) popup.cgi
#!/usr/local/bin/perl
use CGI;
$query = new CGI;
print $query->header;
print $query->start_html('Popup Window');
if (!$query->param) {
print "<Hl>Ask your Question</Hl>\n";
print $query->startform(-target=>'_new');
print "What's your name? ",$query->textfield('name'); .
print "<P>What's the corobination?<P>",
$query->checkbox_group(-name=>'words',
-values=>['eenie','meenie','minie','moe'],
-defaults=>['eenie','moe']);
print "<P>What's your favorite color? ", $query->popup_menu(-name=>'color',
-values=>['red','green','blue','chartreuse']), "<P>";
print $query->submit; print $query->endform;
} else {
print "<H1>And the Answer is...</H1>\n";
print "Your name is <EM>",$query->param(name),"</EM>\n";
print "<P>The keywords are: <EM>",
join(", ",$query->param(words)),"</EM>\n"; print "<P>Your favorite color is <EM>",
$query->param{color),"</EM>\n";
}
print qq{<P><A HREF="cgi_docs.html">Go to the documentation</A>};
print $query->end_html;
Вопросы для самоконтроля
1. Что обозначает аббревиатура CGI?
2. Что такое Web-сервер?
3. Что такое клиент Web-сервера?
4. Для чего нужна HTML-форма?
5. Какую первую строку должна выводить CGI-программа?
6. Какие методы передачи данных формы Web-серверу вы знаете? В чем их особенности?
7. Перечислите элементы управления, которые может содержать форма.
8. Как кодируется информация, передаваемая CGI-программе?
9. В чем заключается специфика CGI-сценариев?
10. Каким образом CGI-программа имеет доступ к переменным среды CGI?
11. Какая информация содержится в переменной среды QUERY_STRING?
12. Для чего предназначен модуль CGI.pm?
Архив СРАМ
Архив СРАМ
CPAN (Comprehensive Perl Archive Network) представляет гигантское храншщ-ще практически всех документов и исходных текстов Perl, а также информацию и исходные тексты огромного количества модулей, расширяющих возможности языка Perl и упрощающих программирование на нем. Если у вас возникла проблема, требующая решения, загляните на CPAN и внимательно посмотрите среди предлагаемых там модулей — может быть, в каком-нибудь из них эта или схожая задачи уже решены. Все модули на CPAN 1 свободно распространяемые, и вы можете бесплатно загрузить и установить на собственном компьютере любой из них. Попасть в архив CPAN можно по адресу:
На домашней странице этого Web-узла можно найти ссылки на документацию в разных форматах, архив конференции news:comp.lang.perl.annouiice, начиная с 1995 года, ссылки на страницу модулей и программы Perl для работы с аудиофайлами, администрирования, обработки почты, организации поиска, автоматизации в Web, организации сетевого взаимодействия и написания CGI-еценариев. Здесь же находится ссылка на двоичные дистрибути-i вы (порты) Perl для разных платформ и на файл с часто задаваемыми вопросами.
В сети Internet, кроме Web-узлов, существуют ресурсы, на которых хранятся файлы с разнообразной информацией. Это так называемые FTP-серверы. Многие из них предоставляют возможность свободной загрузки на компьютер пользователя хранящихся на них файлов по протоколу FTP. Все, что находится на основном узле архива CPAN, доступно через многочисленные FTP-серверы, которые являются обычными копиями (узел-зеркало) содержимого основного узла. На всех узлах-зеркалах содержится совершенно идентичная информация. Организация FTP-сервера архива CPAN представлена в табл. 16.1.
Таблица 16.1. Организация архива CPAN
Файл или каталог | Описание | ||
README.html | Основной документ | ||
CPAN.html | Описание организации архива CPAN, ссылок на все модули и внесения в CPAN собственного модуля | ||
ENDINGS | Описание содержимого файлов в соответствии с их расширением | ||
SITES.html | Список FTP-серверов и Web-узлов архивов CPAN | ||
RECENT . html | Последние поступления | ||
RQADMAP.html | Организация архива CPAN | ||
authors/ | Каталог модулей и расширений Perl, классифицированных по авторам | ||
clpa/ | Каталог архивов групп новостей comp.lang.perl.announce | ||
doc/ | Каталог, содержащий документацию Perl | ||
indeces/ | Каталог, содержащий файлы с указателями на ресурсы CPAN | ||
misc/ | Каталог, содержащий разнообразные ресурсы Perl, не вошедшие ни в один из перечисленных разделов | ||
modules/ | Каталог модулей и расширений Perl | ||
ports/ | Каталог двоичных дистрибутивов Perl для разных платформ | ||
scripts/ | Каталог разных скриптов Perl на разные случаи жизни (просмотрите содержимое этого каталога, если не хотите изобретать велосипед!) | ||
src/ | Каталог исходных текстов и исправлений самого Perl и вспомогательных утилит |
Попасть на один из FTP- серверов архива CPAN можно по ссылке с домашней страницы архива (www.cpan.org) или по одному из следующих адресов, взятых из большого списка FTP-серверов, содержащихся в файле SITES.html: ftp://ftp.flmet.fi/pub/languages/perl/CPAN/ (Финляндия)
fitp://ftp.rz.nilir-uiii-bochum.de/pub/CPAN/ (Германия)
ftp://siinsite.aac.dk (Дания)
ftp://ftp.chg.ru/pub/Iang/perI/CPAN/ (Россия)
ftp://ftp.sai.msu.su/pub/lang/peri/CPAN/ (Россия)
На этом наше первоначальное знакомство с языком Perl заканчивается. Мы надеемся, что читатель, вдумчиво анализировавший все приводимые в самоучителе примеры, добросовестно выполнявший упражнения и отвечавший на предлагавшиеся в конце каждой главы вопросы, сможет теперь самостоятельно продолжить углубление своих знаний в этом интересном и полезном языке программирования. Приведенные в данной главе ссылки на ресурсы Perl в Internet помогут ему в этой благородной задаче.
Конференции
Конференции
Язык Perl распространяется и развивается в глобальной сети Internet. Самые последние новости из мира Perl можно найти на многочисленных Web-узлах и просто обычных страницах HTML, авторы которых являются апологетами языка Perl и входят в так называемое сообщество Perl — свободное объединение людей, использующих и развивающих язык Perl там, где требуется что-нибудь и как-нибудь автоматизировать. Задав в любой поисковой машине (например, AltaVista, Yahoo) поиск по ключевому слову "Perl", вы получите тысячи ссылок на различные ресурсы Internet, так или иначе связанные с языком Perl и программированием на этом языке. Чтобы читатель не запутался и не растерялся в этом обилии информации, мы решили в последней главе нашего самоучителя отметить основные ресурсы Internet — конференции, Web-узлы и FTP-серверы, с которых можно и стоит начинать вхождение в многообразный и интересный мир Perl.
Конференции, или группы новостей Usenet, — это такие ресурсы Internet, куда люди могут посылать статьи со своими мыслями или вопросами на те мы, обсуждаемые в конференции. Если поднятый вопрос заинтересует кого-либо из участников конференции, то могут разгореться жаркие дебаты.
Не советуем сразу же посылать в конференции Perl свои вопросы. Прежде всего ознакомьтесь с их содержанием, так как вполне возможно, что подобные (или близкие) темы в них уже обсуждались, и ваш аналогичный вопрос может вызвать раздражение участников.
В Internet существуют пять известных конференций, в которых обсуждаются вопросы Peri-программирования:
news://comp.lang.perl — основная группа новостей, с которой рекомендуется начинать при поиске необходимой информации;
news://comp.Iang.perl.announce — публикуется информация о новых модулях Perl;
news://comp.lang.perl.modules — дискуссии об использовании модулей, именно здесь можно найти информацию о новых версиях модулей;
news://comp.lang.perl.misc — здесь обсуждается информация, не вошедшая в другие группы новостей;
news://comp.lang.perl.tk — обсуждаются проблемы использования модуля тк для создания интерфейса пользователя.
Регулярное чтение указанных конференций может дать вам больше знаний, чем чтение книг по языку Perl (мы не имеем в виду получение базовых знаний о нем), так как обсуждаемые в конференциях вопросы возникают в результате повседневной практической деятельности большинства их участников. В книгах обычно отражается накопленный к определенному моменту времени практический опыт автора, но новые задачи-то продолжают возникать.
Здесь же мы хотим дать один небольшой, но полезный совет: прежде чем начинать поиск ответа на возникший вопрос в конференциях, обратитесь к файлу, содержащему часто задаваемые вопросы, или, как его еще называют, файл Perl FAQ (Frequently Asked Questions). Его можно найти по адресу:
Специализированные Web-узлы Perl
Специализированные Web-узлы Perl
Группы новостей — интересные и полезные места обмена информацией, но доступ к ним зависит от вашего поставщика услуг Internet. He все они предоставляют доступ к конференциям с помощью своего сервера новостей, а если и предоставляют, то может оказаться, что именно той конференции, о которой вы мечтали, в списке доступных нет. В таких случаях следует обратить свое внимание на Web-узлы, полностью или частично посвященные языку Perl. И первым в этом ряду следует назвать Web-узел, расположенный по адресу
Этот узел является, если можно так сказать, официальным "представителем" информации по языку Perl. Здесь всегда можно узнать последние новости из мира Perl: какая версия интерпретатора считается устойчивой, а какая находится в разработке, где найти и как можно загрузить их на свой компьютер. Узел содержит обширную информацию о реализациях языка на различных платформах (UNIX, Linux, Win32, Mac, OS2 и др.), документацию по последней версии языка и многое другое. Здесь же имеются ссылки на интересные статьи и разработки.
На других многочисленных Web-узлах можно найти учебные пособия и книги по языку Perl, материалы конференций, разнообразные советы по программированию на языке Perl и многое другое. Мы включили в приводимый ниже список только небольшую часть узлов Internet, имеющих отношение к Perl и наиболее интересных с нашей точки зрения:
— узел издательства O'Reilly, на котором можно найти и приобрести книги по языку Perl, ссылки на другие узлы, а также последние новости;
— здесь расположены материалы третьей конференции по языку Perl, проходившей с 21 по 24 августа 1999 года;
— дискуссионный форум по программированию на языке Perl;
— узел некоммерческой организации, поддерживающей сообщество Perl;
— можно найти разнообразные советы по программированию, электронные учебники как для начинающих, так и для тех, кто желает углубить свои знания по языку Perl;
— здесь можно найти реализацию с помощью Perl интересных задач;
— архив статей о Perl, начиная с 1996 года;
— статьи, посвященные сравнению языка Peri с языками программирования Tel, Python, Java, С, csh и др.
— интерактивная база данных по часто задаваемым вопросам, позволяет осуществлять поиск на основе запроса пользователя;
— интересный узел, посвященный проблемам создания Интернет-приложений, в том числе и на базе языка Perl;
— узел фирмы ActiveState Tool Co., на котором имеются свободно распространяемые двоичные версии интерпретаторов для различных платформ: UNIX, Linux, Win32 и Mac.
Мы перечислили только очень небольшую часть адресов Web-узлов, на которых можно найти информацию по Perl. На узлах многих университетов существует описание курсов, посвященных изучению языка Perl и его применению для решения задач Web-программирования и системного администрирования.