Сайт о телевидении

Сайт о телевидении

» » Perl скрипты. Приемы отладки скриптов. Пример: Добавление в середину существующего файла

Perl скрипты. Приемы отладки скриптов. Пример: Добавление в середину существующего файла

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

А при повременной оплате за Интернет отладка CGI-скриптов становится также довольно дорогим занятием:).

Целью данной статьи является представить некоторые способы и приемы, призванные, по мнению автора, заметно упростить процесс отладки CGI-скриптов на Perl, а также указать на некоторые самые распространенные ошибки при их написании.

Подготовка рабочей среды.

Для работы по написанию и отладке CGI-скриптов на Perl удобно использовать локальный Web-сервер, т.е. Web-сервер, установленный на Вашем компьютере. При этом с точки зрения браузера работа с таким сервером ничем не будет отличаться от работы с сервером в Интернет. В качестве локального веб-сервера можно использовать практически любой веб-сервер по Windows; надо только, чтобы он поддерживал запуск CGI-скриптов.

Из самых простых вариантов можно предложить PWS (Personal Web Server) из комплекта Windows9x или IIS (Internet Information Server) из NT. Однако, если Ваш сайт использует такие вещи, как SSI, то лучше все-таки установить Apache для Windows. У большинства сегодняшних хостинг-провайдеров стоит Apache Web Server под UNIX-ом, так что такая совместимость не помешает. Кроме того, Apache позволяет использовать дополнительные нестандартные переменные среды CGI, так что CGI-скрипты, которые "в реальности" будут работать на Apache, лучше отлаживать именно на нем (хотя это мое мнение).

Локальный сервер имеет "доменное имя" localhost и IP-адрес 127.0.0.1 . Соответственно, обращение к нему ведется через URL вида:

Http://localhost/ ...

Однако для исполнения CGI-скриптов на Perl установка Web-сервера недостаточна, надо установить еще и сам Perl. Я бы порекомендовал Perl for Win32 от ActiveState. После установки Perl его нужно "прописать" в установках Web-сервера так, чтобы он являлся Script Handler-ом для Perl-скриптов. В разных Web-серверах это делается по-разному, прочитайте документацию к своему серверу. Для PWS и IIS установка Perl - задача особенная. В большинстве веб-серверов для Windows принадлежность CGI-скрипта к определенному "типу" (Perl-скрипт, еще какой-то скрипт...), а соответственно и handler-у определяется по расширению имени файла. Если на Вашем сервере это так, надо установить для CGI-скриптов на Perl такое расширение, какое оно у Вашего хостинг-провайдера (стандартом де-факто является *.cgi, всречается и *.pl). В Apache принадлежность скрипта определяется не по расширению, а по строчке "#!..." в начале скрипта, как почти во всех UNIX-серверах.

При установке всего вышеизложенного для нас очень важна возможность запускать Perl-скрипты "без веб-сервера", т.е. как обычные программы. Это очень удобно при проверке их на синтаксические ошибки.

Проверить правильную установку всего можно, написав простой скрипт:

#!(путь к Перл) print "Content-Type: text/plain ; charset=windows-1251\n\n"; print "";

Сохраните этот скрипт в файле, например, test.cgi и положите этот файл в вашу cgi-bin папку.

Теперь проверьте работу скрипта, запустив браузер и выполнив URL:

Http://localhost/cgi-bin/test.cgi

Если все нормально, вы должны увидеть в окне браузера следующий вывод:

Скрипт отработал успешно! Поздравляю!

Если же Вы вместо этого вывода скрипта увидели на экране сам скрипт или нечто вроде "Access Denied" , "Permission Denied" , "Forbidden" или ничего не увидели вообще (как при загрузке "пустого" документа), то проверьте настройки Вашего веб-сервера - скорее всего, у Вас неверно установлены права доступа на Вашу cgi -папку.

Теперь попробуем запустить наш CGI-скрипт как обычную программу на Perl. Зайдем в какую-нибудь команднострочную оболочку (например, FAR manager) и наберем:

Perl (адрес Вашего скрипта)

В результате Вы должны увидеть вывод:

Скрипт отработал успешно! Поздравляю!

Вместо слов в последней строчке возможна "абракадабра" - это ничего страшного; просто несоответствие кодировок в скрипте и в оболочке, в которой мы его исполняем. Главное, чтобы он заработал.

Если оба вышеуказанных теста прошли успешно - поздравляю! Теперь Вы можете отлаживать большинство CGI-скриптов на своем компьютере, не платя провайдеру за это ни копейки! Теперь у Вас есть свой маленький "интернет в миниатюре" :)))

Приемы отладки скриптов.

Довольно распространенной синтаксической ошибкой является пропуск ";" в конце оператора. (особенно это характерно для тех кто привык к Бейсику, где разделитель строки является разделителем между операторами. В Perl, как и в C/C++, все переводы строки, возвраты каретки и табуляции приравнены по значимости к пробелу и называются "пробельными символами". Разделителями операторов они не являются. Единственным исключением является их использование в строковых константах, где они являются "сами собой", но это только подтверждает правило, что они не разделяют операторы.)

Итак, если Ваш скрипт содержит синтаксическую ошибку, то сообщение об этой ошибке все равно до браузера не "дойдет". Чаще всего при синтаксической ошибке в скрипте сервер выдает ошибку "500 Internal Server Error". Что ж, это действительно считается "внутренней ошибкой сервера"... Вот только в какой она строке?!

Но ведь мы теперь можем запустить CGI-скрипт "как программу", и увидеть сообщение Perl об ошибке!

Если в вышеуказанном скрипте сделать намеренную ошибку, убрав ";" в конце предпоследней строки, то запустив его "через сервер", мы скорее всего увидим большими буквами написанное "500 Internal Server Error" (Внутренняя ошибка сервера). А если мы запустим его "как программу", то увидим сообщение наподобие следующего:

Syntax error at test.cgi line 3, near "print" Execution of test.pl aborted due to compilation errors.

В первой строке указано, что синтаксическая ошибка произошла в файле test.cgi, в строке 3, рядом со словом print. По-моему, довольно исчерпывающая информация! :) (во второй строке сказано, что выполнение скрипта прервано из-за ошибок компиляции).

Теперь мы ищем строку 3, оператор print и исправляем ошибку. Также довольно неприятной ошибкой, приводящей к, на первый взгляд, совершенно непонятному поведению скрипта, является пропуск закрывающей фигурной скобки (}). Чаще всего Perl определит это как ошибку компиляции, но у меня были случаи, когда ошибки не выдавалось. Вообще, все ошибки в CGI-скриптах можно, на мой взгляд, условно разделить на следующие категории:

  1. Синтаксические (ошибки компиляции);
  2. Ошибки взаимодействия с CGI;
  3. Ошибки взаимодействия с другими программами и/или файлами;
  4. Логические.

Первые ошибки удобнее всего находить описанным выше способом.

Ко вторым относится некорретный вывод скрипта: скрипт должен выводить свой ответ в формате HTTP, т.е. поля заголовка ответа, затем - пустая строка, а затем - собственно тело ответа. В описанном выше примере выводилась строка заголовка:

Content-Type: text/plain ;charset=windows-1251

затем-пустая строка - и тело ответа:

Скрипт отработал успешно! Поздравляю!

При этом сервер, получив ответ от скрипта, разбирает выданный им заголовок, добавляет в него дополнительные поля и основную строку ответа. Поэтому CGI-скрипту вовсе необязательно формировать полный заголовок. Обычно обязательным является указание поля Content-Type, но в любом случае пустая строка после заголовка обязательно должна быть

Несколько слов о так называемых nph- CGI-скриптах. Это скрипты, полностью формирующие HTTP-заголовок. Поэтому сервер не должен "разбирать" заголовки, выданные такими скриптами, а передавать браузеру все "как есть". Отсюда и название - nph (non-parsed headers - неразбираемые заголовки). Для некоторых серверов такие скрипты должны иметь определенное строение имени файла (имя должно начинаться с nph-), для других это не обязательно.

Также к ошибкам связи с CGI относится неправильное указание переменных среды CGI, а также - для скриптов, обрабатывающих формы - метода передачи данных от формы (GET или POST). При этом, если скрипт ожидает данных, посланных методом POST (на стандартный ввод), а в форме ошибочно указан метод GET, то скрипт "застрянет" - он будет ждать поступления данных на стандвртный ввод! Если же скрипт принимает данные по методу GET, а в форме указан POST, скрипт отработает, но не получит из формы никаких данных (как если бы в форме не было ни одного поля).

Для скриптов, выводящих "картинки" (GIF, JPG), характерной ошибкой является ASCII-режим передачи. Сразу после открытия файла оператором open этому файлу соответствует ASCII-режим чтения/записи, предназначенный для "простых текстов" (text/plain), как, например, текст в "блокноте".

Все файлы, которые задействованы в выводе картинки, (в том числе STDOUT !) должны быть переведены в "бинарный" режим Perl-оператором:

Binary FILE;

Иначе произойдет искажение данных, поскольку он будет передаваться как текст: во-первых, произойдет замена "концов строк", во-вторых, символ с кодом 0 будет воспринят как конец файла.

К ошибкам связи с внешними программами и файлами можно отнести неверный вызов, например, UNIX-команд sendmail, date и т.п. Сюда же можно отнести и неправильный путь к Perl, записанный в первой строке после #!.

Как же отлаживать на локальной машине скрипты, использующие, скажем, sendmail, если у Вас (под Windows) нет sendmail? Наиболее простой способ - закомментировать то место скрипта, которое высылает письмо. Оно скорее всего в общем случае имеет вид:

Open EMAIL,"|путь_к_sendmail список_получателей"; print EMAIL "...."; .... close EMAIL;

где в операторе open открывается sendmail, EMAIL - дескриптор файла; может быть любой. Таким образом, можно проверить работу скрипта без высылки сообщения по E-Mail, если оно является вспомогательным (скажем, в гостевых книгах, высылающих вебмастеру уведомление о новой записи).

Можно поступить и другим путем: вместо открытия sendmail в команде open записать открытие файла на запись. Ничего другого при этом менять не нужно.

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

Кстати, поскольку E-Mail адрес имеет вид user@hostname , а символ @ в Perl- обозначение массива, то "прямая" запись такого адреса вызовет ошибку! Поэтому перед @ нужно ставить обратный слэш \ . То есть адрес в строчке Perl должен иметь вид user\@hostname . То же самое относится и к другим зарезервированным символам, например, $ .

Относительно команды date можно сказать, что в большинстве случаев ее может заменить функция perl

Scalar localtime

которая возвращает строку с текущей датой/временем, например:

Sun Oct 22 16:11:42 2000

Такая замена вполне возможна, если полученное значение даты/времени не разбирается CGI-скриптом, а просто записывается в лог-файл (или используется "как есть" по-другому).

Таким образом, в большинстве случаев работу скрипта можно проверить даже при отсутствии необходимых ему программ, стандартных для UNIX.

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

Окончательная отладка CGI-скриптов на сервере.

Итак, Ваш скрипт работает на локальном компьютере прекрасно, теперь настало время перенести его на сервер.

Итак, на что следует обратить внимание:

1. Путь к Perl в первой строчке.

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

2. Пути к другим программам, используемым CGI-скриптом.

3. Имена файлов, к которым обращается скрипт.

В Windows нет различий между заглавными и строчными буквами в именах файлов, т.е. A.TXT и a.txt - идентичные имена. В UNIX, на базе которого работает большинство интернет- серверов, заглавные и строчные буквы в именах файлов - различные символы. Таким образом, скрипт, открывающий файл a.txt командой:

Open FILE,"a.TXT";

будет нормально работать под Windows, но не захочет работать под UNIX (файл не будет найден).

4. Режим закачки файлов на сервер.

Наиболее частой ошибкой является закачивание всего сайта в "бинарном" режиме. И если с закачанными в таком режиме html и txt - файлами особых проблем не будет (хотя могут возникнуть), закачанные таким образом скрипты работать _не будут_. Все файлы CGI-скриптов, а также используемых ими текстовых файлов, должны быть закачаны в ASCII-режиме.

5. Права доступа к файлам.

Даже если все сделано правильно, скрипт после закачки на UNIX-сервер вряд ли сразу начнет работать.

Для того, чтобы он начал работать, надо установить права доступа для файлов CGI-скрипта и используемых ими файлов.

Как правило, сразу после закачки файлов на сайт им всем устанавливаются некоторый "стандартный" набор прав (по умолчанию), например:

Rw-r--r--

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

  1. Файлы CGI-скрипта;
  2. Файлы, используемые CGI-скриптом для чтения;
  3. Файлы, которые CGI-скрипт использует для чтения и записи;

Как правило, хостинг провайдер, разрешающий использование CGI, указывает, какие права доступа должны быть установлены для файлов каждого типа.

Если нет, то в качестве компромисса можно использовать следующие установки:

CGI-скрипт - -rwx-r-x-r-x (755); Файлы для чтения - -rw-r--r-- (644); Файлы для записи - -rw-rw-rw- (666);

ВНИМАНИЕ! На некоторых хостингах рекомендуются другие, более строгие конфигурации прав доступа, обеспечивающие более надежную защиту от взлома для Вашего сайта и системы в целом! Поэтому следуйте рекомендациям своего хостинг-провайдера, если они есть!

Андрей Новиков

Что такое Perl?

Perl является интерпретируемым языком, созданным программистом Лари Уоллом (Larry Wall) для обработки больших текстов и файлов и расшифровывается, как Practical Extraction and Report Language (язык для практического извлечения данных и составления отчетов). С помощью Perl вы, например, можете создать скрипт, который открывает один или несколько файлов, обрабатывает информацию и записывает результаты.

С изобретением World Wide Web, Perl оказался прекрасным средством для взаимодействия с web-серверами через Common Gateway Interface (CGI) - общий интерфейс взаимодействия. Команды Perl могут легко получить данные из формы HTML или другого источника и что-нибудь с ними сделать.

Как Perl обрабатывает данные из форм

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

  • добавить их в текстовый файл,
  • ввести их в базу данных,
  • вставить их в электронное письмо,
  • добавить их в существующую web-страницу,
  • создать новую web-страницу,
  • отобразить их в окне браузера.

Некоторые из этих примеров рассматриваются в нашем уроке.

Как генерируются web-страницы "на лету"

Больше всего впечатляет то, что Perl может быть использован для создания web-страниц "на лету" в ответ на запрос или действие пользователя. Новая страница может быть

  • благодарностью за заполнение формы
  • страницей подтверждения с возможностью редактирования
  • запросом дополнительных данных
  • результатом запроса к базе данных или запроса поиска

Эта возможность обеспечивает истинную интерактивность вашего узла. Такие скрипты позволят web-серверу автоматически реагировать на определенный набор запросов пользователя, предоставляя данные в требуемом пользователем виде.

В чем различие между программой и скриптом?

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

За счет того, что скрипты значительно короче программ, они выполняются тоже достаточно быстро.

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

Альтернативы Perl

Существует несколько альтернатив использованию Perl:

  • С, Visual Basic - более традиционные компьютерные языки для обработки вводимых данных. Должны компилироваться под определенную платформу.
  • ActiveX - включение программных компонент, выполняющихся в браузере.
  • JavaScript, VBScript - обеспечивают некоторую интерактивность HTML страниц, которую HTML обеспечить не может.
  • Cold Fusion - сторонняя программа для связи форм с базами данных.
  • PHP/FI - еще одна сторонняя программа для связи форм с базами данных.

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

Что вам требуется, чтобы запустить Perl

Для запуска Perl вашей системе понадобится несколько компонент:

  1. Скрипт, написанный вами или предложенный вам другим, сохраненный в текстовом файле.
  2. Perl интерпретатор. Любой Perl скрипт в первой строке содержит путь к этой программе.
  3. Web-страница с которой будет запускаться этот скрипт. Она может содержать форму или просто ссылку, если скрипт не требует входных данных.
  4. Web-сервер. Взаимодействие между web-страницей и скриптом производится сервером. Поэтому вы должны иметь доступ к web-серверу с возможностью записи и запуска на нем скриптов.

Где взять Perl

Существует много различных мест, где можно получить информацию о последних версиях Perl.

  • Общая информация о Perl - http://www.perl.com/perl/index.html
  • Perl для UNIX - http://www.perl.com/perl/info/software.html
  • Perl для Win32 - http://ntperl.hip.com

Этапы создания скрипта

После того, как вы установили на своем компьютере необходимое ПО, нужно совершить несколько шагов для запуска Perl на вашем узле:

  1. Создать форму для вызова скрипта.
  2. Создать сам скрипт.
  3. Отладить скрипт. Проверить отсутствие ошибок (если это возможно, лучше проверить все возможные пути выполнения программы).
  4. Поместить скрипт на сервер и не забыть дать ему права на выполнение.
  5. Связать скрипт с формой, вставив его имя в параметр action тэга form. Например:
  1. Убедиться, что скрипт правильно работает вместе с формой.

Основные части Perl скрипта

В общем случае любой Perl скрипт состоит из четырех ключевых частей:

  1. Настойка . Первая часть скрипта обязательно запускает интерпретатор и устанавливает переменный, используемые в теле скрипта. Для запуска интерпретатора необходимо знать правильный путь к программе.
  2. Чтение входных данных . Эта часть "считывает" и сохраняет в переменных входные данные в удобной для обработки форме. Эта часть обычно неизменна во всех скриптах.
  3. Обработка входных данных . Эта часть соответствующим образом обрабатывает введенные данные. Она может быть простой (около 5 строк) или очень сложной (более 1000 строк) в зависимости от выполняемой задачи.
  4. Вывод результатов . Пользователь обычно ожидает какого-либо ответа на свои действия. Эта часть достаточно проста в реализации.

Пример скрипта с формой

Рассмотрим теперь описанные нами шаги на конкретном примере. От вас не требуется понимания каждой строки скрипта, все они будут объяснены ниже.

Шаг 1 - Создание формы

Создадим для простоты форму, содержащую всего одно поле и позволяющую пользователю зарегистрировать его имя. Напишем в редакторе следующий текст:

Test Form Введите Ваше имя:

Сохраните файл на диске.

Шаг 2 - Создание скрипта

Предложенный ниже скрипт берет введенные данные, сохраняет их в файле и показывает сообщение, содержащее ссылку на файл с сохраненным именем. Наберите в редакторе текст программы и сохраните в файле testform.pl в каталоге cgi-bin вашего web-сервера. Убедитесь, что первая строка программы содержит правильный путь к программе-интерпретатору (для определения местоположения программы на UNIX воспользуйтесь командой which perl, под Windows выполните поиск файла perl.exe). Убедитесь также, что путь к выходному файлу является корректным путем к области хранения документов web-сервера. В заключение исправьте URL на адрес вашего сервера.

#!/usr/local/bin/perl # <-- ПРОВЕРЬТЕ ЭТО # Read and parse input from the web form read(STDIN, $buffer, $ENV{"CONTENT_LENGTH"}); @pairs = split(/&/, $buffer); foreach $pair (@pairs) { ($name, $value) = split(/=/, $pair); $value =~ tr/+/ /; $value =~ s/%()/pack("C", hex($1))/eg; $value =~ s///g; $input{$name} = $value; } # Save the user output in a file $targetfile = "/usr/local/www/htdocs/names.html"; # <-- ПРОВЕРЬТЕ ЭТО open (NAMEFILE, ">>$targetfile"); print NAMEFILE "

Имя: ",$input{"user_name"},"

\n"; print NAMEFILE "


\n"; close (NAMEFILE); # Send a message back to the user print "Content-Type: text/html\n\n"; print "

Спасибо, что заполнили форму

\nНажмите "; print "сюда"; # <-- ЗАМЕНИТЕ ЭТО print ", чтобы увидеть Ваш ввод.\n";

Шаг 3 - Тестирование скрипта

Проверив скрипт визуально на наличие ошибок - отсутствие ";" в конце строк, наличие непарных скобок и кавычек и т.п., запустите скрипт для проверки прямо из командной строки, перейдя предварительно в каталог cgi-bin. Вот некоторые примеры того, как это делается:

./testform.pl /usr/local/bin/perl testform.pl c:\perl\perl.exe testform.pl

Если в скрипте содержатся ошибки, то вы увидите сообщение типа

syntax error at testform.pl line 18, near "open" Execution of testform.pl aborted due to compilation errors.

В этом случае проверьте текст около указанной строки. Помните, что причина ошибки может быть выше на несколько, иногда достаточно много строк. Исправленный скрипт сохраните, и тестируйте так до тех пор, пока он не выдаст корректных выходных данных:

Content-Type: text/html

Спасибо, что заполнили форму

Нажмите сюда, чтобы увидеть Ваш ввод.

Шаг 4 - Тестирование скрипта с формой

Если скрипт работает сам по себе, вы можете оттестировать его с формой:

  1. Убедитесь, что web-сервер запущен.
  2. Запустите ваш браузер.
  3. Наберите URL по которому находится ваша форма (обратите внимание, что строка должна начинаться с http://, а не с file://.
  4. Введите ваше имя в поле формы и нажмите кнопку "Зарегистрировать".
  5. Вы должны увидеть сообщение вроде этого:

Спасибо, что заполнили форму
Нажмите сюда , чтобы увидеть Ваш ввод.

Это и есть страница, сгенерированная скриптом "на лету". Если вы получили сообщение об ошибке сервера, проверьте правильность расположения скрипта и правильность значения параметра action в тэге form.

  1. Если вы видите правильно сгенерированную страницу, нажмите на ссылку. Вы должны будете увидеть новую страницу, созданную скриптом примерно в таком виде:

Имя: Новиков

Если вы не видите этого, проверьте правильность пути в переменной $targetfile и правильность URL в предпоследней строке скрипта. В противном случае форма и скрипт правильно работают вместе. Вы успешно создали первое web-приложение.

Обсуждение: Настройка скрипта

Как уже было сказано, первая часть скрипта содержит настройки, включающие в себя несколько элементов. Первая строка определяет путь к программе-интерпретатору:
#!/usr/local/bin/perl для UNIX
или
\Program Files\Perl5\perl.exe для Win32

Также в начале скрипта вы, для удобства, можете разместить комментарий о том, для чего предназначен этот скрипт.

Комментарии могут располагаться в любом месте программы и начинаются с символа #:
# Это комментарий или
open (NAMEFILE, ">$testfile"); #Открываем файл для записи...

Также хорошей манерой является определение в начале скрипта всех констант и глобальных переменных. (Советую все пути прописывать в виде переменных, особенно если программа содержит более 50 строк, для удобства изменения местоположения файлов). Например:
$homepage = "http://server_name/home/index.html";

Все обычные переменные в Perl начинаются с символа $. Существует много других видов переменных, таких как массивы и т.п.

Все строки программы кроме первой и комментариев должны заканчиваться на ";".

Обсуждение: Чтение данных из формы

Теперь необходимо "считать" введенные пользователем данные в переменные Perl. После того как пользователь нажмет кнопку Submit в форме браузер посылает серверу имя скрипта и данные, взятые из формы. Данные передаются скрипту на стандартный вход.

Предположим, что форма содержит следующие поля:

В этом случае данные будут посланы скрипту в следующем формате:
user_name=Andy+Novikov&co_name=TeleSputnik&phone=(812)+123-45-67

Perl скрипт должен разобрать эту строку по частям и сохранить в переменных для дальнейшей обработки. Строки, производящие эти действия достаточно стандартны:
read(STDIN, $buffer, $ENV{"CONTENT_LENGTH"});

Эта строка читает данные со стандартного входа и помещает их в переменную $buffer. Длина строки передается скрипту через переменную окружения CONTENT_LENGTH.

Как только данные помещены в переменную $buffer вы можете разбить их на отдельные переменные с соответствующими им значениями:
@pairs = split(/&/, $buffer);

Теперь мы получили массив @pairs со следующими строковыми переменными:
user_name=Andy+Novikov
co_name=TeleSputnik
phone=(812)+123-45-67

Теперь нам необходимо разбить эти строки на пары параметр-значение:
foreach $pair (@pairs) { ($name, $value) = split(/=/, $pair); $value =~ tr/+/ /; # заменяем плюсы на пробелы $value =~ s/%()/pack("C", hex($1))/eg; $value =~ s///g; $input{$name} = $value; }

Таким образом вы получаете массив переменных, индексом в котором является значение параметра name поля формы, а значением - данные, введенные в соответствующее поле.

Обсуждение: Что делать с данными?

Следующим шагом является обработка данных. Но как? Все зависит от того, что вы хотите сделать с данными. В нашем примере мы на основе полученных данных создаем новый HTML документ. Нише мы рассмотрим несколько простых примеров того, что можно сделать с полученными данными. Обратите внимание, что мы не предпринимаем попыток проверить правильность (validate) содержимого полей. Хотя в реальных скриптах это является желательным, а иногда и необходимым действием.

Обсуждение: Запись в файлы

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

Функция открытия файла выглядит следующим образом:
open (HANDLE, "name"); # Открыть файл для чтения open (HANDLE, ">name"); # Открыть файл для записи open (HANDLE, ">>name"); # Открыть файл для добавления в конец

HANDLE является любым временным именем, который вы будете использовать как идентификатор файла при проведении операций. Как только файл открыт, вы можете писать в него, используя функцию print:
print HANDLE "Этот текст будет помещен в файл как есть.\n"; print HANDLE "В этом случае переменная ",$variable," будет помещена в текст."; print HANDLE "Переменную $variable можно помещать в текст и так.\n"; print HANDLE "Кавычки и др. Спецсимволы \; надо \"подсекать\".\n";

После завершения операций с файлом необходимо его закрыть:
close (HANDLE);

После этого все записанные данные будут сохранены на диск.

Перед осуществлением запись в файл, вы должны убедиться, что web-сервер имеет доступ к директории, в которой находится файл и имеет права на запись в этот файл.

Обратите внимание: функция close должна располагаться как можно ближе к последней функции записи в файл. Это обусловлено тем, что web-сервер выполняется в многопользовательской среде, и скрипт может запускаться одновременно несколькими пользователями. При открытии файла на запись он (файл) блокируется и другие экземпляры скрипта не смогут его открыть, что вызовет задержку в выполнении запроса.

Пример: Создание новой HTML страницы

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

В связи с тем, что мы создаем web-страницу файл содержит тэги HTML вместе с обычным текстом. Помните, что \n просто вставляет перевод строки в текст для удобства последующего просмотра созданного файла.

Все входные данные из формы содержатся в переменных $input{field_name}. При печати такие переменные должны выноситься за кавычки и отделяться запятыми.

# Определяем переменную, содержащую путь к записываемому файлу $newfile = "c:\webserver\htdocs\mynewpage.html"; # Открываем файл, используя идентефикатор USERINFO open (USERINFO, ">$newfile"); # Формируем содержимое print USERINFO "\n\n"; print USERINFO "Информация о регистрации\n\n"; print USERINFO "\n\n

Данные регистрации:

"; print USERINFO "\n

\n"; print USERINFO "Имя: ", $input{"user_name"},"\n
"; print USERINFO "Компания: ", $input{"co_name"},"\n
"; print USERINFO "Телефон: ", $input{"phone"},"\n

\n\n"; print USERINFO "\n\n\n"; # Закрываем файл close (USERINFO);

Пример: Добавление в конец файла

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

# Определяем переменную, содержащую путь к записываемому файлу $targetfile = "c:\webserver\htdocs\mynewpage.html"; # Открываем файл, используя идентификатор NEWINFO open (NEWINFO, ">>$targetfile"); # Добавляем новые данные в файл: print NEWINFO "\n\n"; print NEWINFO "Имя: ", $input{"user_name"},"\n
"; print NEWINFO "Компания: ", $input{"co_name"},"\n
"; print NEWINFO "Телефон: ", $input{"phone"},"\n

\n\n"; close (NEWINFO);

Пример: Добавление в середину существующего файла

Более сложной задачей является вставка новых данных в середину файла. Обратите внимание, что в первом примере мы вставили в файл линию комментария, выглядящую следующим образом:

Этот комментарий будет служить нам меткой места, в которое нужно вставлять новые данные. Данный пример содержит не совсем изящное решение, но прост в реализации и понимании. Он использует временный файл, хотя можно обойтись и без него:

# Определяем переменную, содержащую путь к исходному файлу $origfile = "/pathname/originalfile.htm"; # Определяем переменную, содержащую путь к временному файлу $newfile = "/pathname/newfile.htm"; open(INFILE, "<$origfile"); open(OUTFILE, ">$newfile"); while ($line = ) { printf OUTFILE $line; if ($line =~ //i) { # Добавляем новые данные в файл: print OUTFILE "\n\n"; print OUTFILE "Имя: ", $input{"user_name"},"\n
"; print OUTFILE "Компания: ", $input{"co_name"},"\n
"; print OUTFILE "Телефон: ", $input{"phone"},"\n

\n\n"; } } # Закрываем файлы close(INFILE); close(OUTFILE); # Удаляем исходный файл и переименовываем новый в исходный unlink($origfile); rename($newfile, $origfile);

Пример: Отправка данных по e-mail

Иногда вам может потребоваться, чтобы данные введенные в форму были посланы по некоторому адресу электронной почты.

Для этого вам потребуется программа посылки почты с интерфейсом командной строки. Под UNIX это может быть sendmail или mail. В данном примере данные посылаются с помощью программы sendmail. Вместо записи в файл мы используем запись в специально открытый канал (pipe):

# Адрес e-mail $sendto = "webmaster\@telesputnik.ru"; # Открываем канал open (MAIL, "| /usr/bin/sendmail $sendto") # Печатаем в канал в специальном формате print MAIL "From: Web-сервер\n"; print MAIL "To: $sendto\n"; print MAIL "Subject: Ввод новых данных"; print MAIL "Кто-то воспользовался формой для ввода новых данных"; print MAIL "Вот что он ввел:"; print MAIL "Имя: ", $input{"user_name"},"\n"; print MAIL "Компания: ", $input{"co_name"},"\n"; print MAIL "Телефон: ", $input{"phone"},"\n "; # Посылаем письмо, закрывая канал close (MAIL);

Обсуждение: Создание web-страниц "на лету"

Последней важной частью Perl скрипта является посылка результата обратно пользователю. Это достигается тем же print, но без идентификатора файла или канала. Все, что печатается на стандартный выход формирует текущий документ в окне браузера. Например:

print "Content-Type: text/html\n\n"; print "\n\nСпасибо\n"; print "\n

Спасибо за заполнение формы

"; print "Мы получили ваше имя, место работы и телефон,"; print " которые вы видите ниже:
\n"; print "Имя: ", $input{"user_name"},"\n
"; print "Компания: ", $input{"co_name"},"\n
"; print "Телефон: ", $input{"phone"},"\n

\n\n"; print "\n";

Обратите внимание на первую строку. Эта строка содержит информацию о типе возвращаемых данных. Двойной перевод стоки при этом обязателен. Эта страница будет возвращена пользователю почти сразу после нажатия им кнопки Submit.

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

Был занят, занимался самообразованием, т.к. почувствовал что погряз в одном и том же. Расширяю кругозор, узнаю новое, к чему то стремлюсь, это очень интересно и занимает очень много времени.

Теперь по делу.

Операционная система у меня ubuntu ++ постоянно по работе приходится сидеть в консоли. Очень часто возникает задача, быстро по шаблону поменять что то в файле. Ответ на вскидку = sed. В свое время я читал про него, но понял что при помощи perl могу делать то же самое. Прошло время, sed я забыл совершенно, а вот perl тоже стал забываться, и я постоянно не могу найти пример однострочных скриптов.

Теперь по порядку.

Дано.
Есть файл xx.txt в котором лежат числа от 1-го до 5-ти, каждое число, новая строка.



1
2
3
4
5

Хочется заменить все вхождения строки 3 на что то свое, пусть это будет строка "hello"

Решение:

cd@laptop:~/data/tmp$ perl -ig -ne "s/3/hello/;print $_; " xx.xx
cd@laptop:~/data/tmp$ cat xx.xx
1
2
hello
4
5


cd@laptop:~/data/tmp$ perl -ig -pe "s/3/hello/; " xx.xx
cd@laptop:~/data/tmp$ cat xx.xx
1
2
hello
4
5
cd@cd-acer:~/data/tmp$ ls *g
9.jpg xx.xxg

Объяснение.

perl позволяет запускать однострочные скрипты, не создавая файл с кодом скрипта.

Пример:

cd@laptop:~/data/tmp$ perl -e "print "test\n""
test
cd@laptop:~/data/tmp$

За это отвечает опция -e после которой идет код для выполнения.

Однострочные скрипты, после кода, могут принимать параметром файл, а также, можно заставить выполнять код указанный -e для каждой строки.

Пример:

cd@laptop:~/data/tmp$ perl -ne "print ;" xx.xx
1
2
hello
4
5

Т.е. в данном случае мы попросили перл, выполнить распечатку строки по умолчанию, а т.к. была указана опция -n то это команда применялась к каждой строке файла xx.xx, т.е. получили cat

Также существует параметр -p, который после выполнения кода распечатывает строку. Т.е. логично что команда вида


perl -ne "dosmth; print $_;" file

будет аналогична

perl -pe "dosmth" file

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


perl -i -pe "dosmth" file

выполнит код dosmth для отдельно взятой строки и заменит ее в указанном файле.

опция -i может принимать необязательный параметр, и тогда, скрипт перед началом работы сделает backup копию файла


cd@laptop:~/data/tmp/1$ perl -ibak -ne "print;" 1.txt
cd@laptop:~/data/tmp/1$ ls
1.txt 1.txtbak
cd@laptop:~/data/tmp/1$ cat 1.txt
1
2
3
cdlaptop:~/data/tmp/1$ cat 1.txtbak
1
2
3
cd@laptop:~/data/tmp/1$

Теперь само решение должно быть понятно, а также понятно почему я привел два варианта.

Появилась простая задачка, в одном из конфигов нужно увеличивать на единицу одно из значений, пусть условно это будет номер билда.

Возьмем пример файла конфига

cd:$ cat config
Key1 Value2
build=projectname.005
one more line

Допустим нам нужно получить такой же конфиг но с build=projectnam.006


perl -i -pe "s/(projectname\.)(\d+)/sprintf("%s%03d", $1, $2+1)/e" config

Пояснения.

I -pe объяснялось выше.

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

Можно было бы конечно сделать что то вроде


perl -pe "s/(projectname\.)(\d+)/$1 . ($2+1)/e" config
Key1 Value2
build=projectname.6
one more line

! опция -i была убрана, я хотел чтобы файл не менялся, а результат был в output

Как видим пропадают два ведущих нуля, именно поэтому была использована функция sprintf

4 comments:

Анастасия said...

Спасибо. Пригодилось:)
Если нет возражений, я дала на Ваш блог ссылку в своем http://aal-blog.blogspot.com/2009/10/stroka1-stroka2.html

said...

Без проблем. Рад хоть что то пригодилось.

Anonymous said...

Есть вопрос...
Возможно ли запуская скрипт дать ему на обработку данные.
Например запускаю скрипт совмещения двух баз там идёт запрос месяцев... потом передача вывода на печать...
тоесть хотелось бы чтоб данные поступали в скрипт с запуском...
Заранее спасибо

Так сложилось, что я знаю как минимум двух человек, которые хотели бы выучить Perl. Специально для них я решил написать этот пост.

  • Часть 1: Типы переменных (вы читаете эту часть)

В нем вы найдете примеры простых программ из серии «вывести числа от 1 до 5» и тому подобное. Мне всегда нравилось учиться на примерах — это интереснее и быстрее, чем по книжкам или на семинарах. Также можете посмотреть посты этого блога, — велика вероятность, что в них вы найдете еще примеры.

Я предполагаю, что в школе/институте вы изучали Pascal/Delphi, C или хотя бы Basic, и объяснять, что такое функция и циклы не требуется. Если это не так — ничего страшного, просто для того, чтобы во всем разобраться, вам придется потратить лишнее время на чтение Википедии. Если вы не знаете, как запустить bash-скрипт, или для чего в первой строке скрипта писать что-то вроде #!/bin/sh , придется немного погуглить , чтобы это выяснить.

Специально для тех, кого интересуют вопросы, «а правда ли, что Perl очень сложен», «а какие книжки по Perl можете посоветовать» и даже «эээ… а что, на нем еще пишут?», я написал Mini-FAQ по Perl , которое вы можете прочитать на HabraHabr. А для тех, кто неасилил многабукв здесь я приведу краткое его содержание:

  • Perl — современный язык программирования, на котором пишут и будут писать еще очень долго.
  • Perl, как и любой другой язык программирования, имеет свои достоинства, недостатки и области применения. Существует действительно большой класс задач, которые Perl решает на 5+.
  • Синтаксис Perl не сложнее синтаксиса C++ или Java. В этом вы сможете убедиться, дочитав данный пост до конца.
  • Существуют хорошие и при этом недорогие учебники по Perl. Также в сети вы без труда найдете сообщество perl-программистов, говорящих на вашем родном языке.
  • Perl хорошо работает как под операционными системами семейства UNIX, так и под Злом Windows.

Дополнение: Также я рекомендую вам ознакомиться со статьями Perl vs Python vs Ruby vs PHP и Жрецы программирования . Первая повествует о производительности различных скриптовых языков, вторая — об отличии PHP от других ЯП. Фанатам Пайтона советую прочитать заметку Тест производительности скриптов на Python . Надеюсь, что эти материалы помогут вам найти ответ на вопрос «чем хорош Perl».

Привет, %username%!

Итак, давайте уже напишем наш первый скрипт на Perl!

#!/usr/bin/perl

$name = shift () ;
print ("Hello, $name!\n " ) ;

Запускаем скрипт:

$ chmod u+x 1 .pl
$ ./ 1 .pl afiskon
Hello, afiskon!

Тут все очень просто:

  • Имена скалярных переменных (то есть не массивов и не хэшей, что это такое — см ниже) начинаются со знака доллара.
  • Функция shift возвращает очередной аргумент скрипта. Другими словами первый вызов shift() возвращает первый аргумент, второй вызов — второй аргумент и так далее.
  • Функция print() выводит строку, переданную в качестве аргумента.
  • В строку можно подставлять значения переменных (см строку 4). Подробнее о строках — см далее.

Если пока не очень понятно — ничего страшного. Возможно, немного теории внесет чуть больше ясности.

Типы переменных

В Perl существует три основных типа переменных: скаляры (числа и строки), массивы — подобно тем, что используются в Pascal или C (иногда массивы еще называют векторами), и хэши (ассоциативные массивы).

Скаляры мы уже использовали в предыдущем примере. Вот еще несколько примеров задания скаляров.

#!/usr/bin/perl

$a = 123 ;
$b = - 7.496 ;
$c = 0xABC; # равно 2748, да, это комментарий:)
$d = ($a + $b ) / $c ;
$d *= $a ; # тоже самое, что $d = $d * $a;

$str1 = "hello" ;
$str2 = "$str1, world" ; # в $str2 записано "hello, world"
$str3 = $a . "\n " . $str2 ;
$str4 = "$str1" ; # в $str4 записано "$str1", а не "hello"

Тут мы задаем положительные и отрицательные, целые и дробные числа, задаем число в шестнадцатеричной кодировке, складываем, умножаем и делим — все как в Си или Java. Кроме перечисленных операций Perl также поддерживает операцию возведения в степень:

$a = 2 ** 8 ; # результат: 256

Со строками все примерно так же, как в каком-нибудь PHP. Точка означает операцию конкатенации (то есть «склеивания» строк), если в строке содержатся имена переменных, на их место подставляются значения, с помощью обратного слэша можно вставлять символы новой строки (\n), табуляции (\t), кавычки (\"), сам обратный слэш (\\) знак доллара безо всякой подстановки переменных (\$) и многое другое. Если строка в одинарных кавычках, символы в ней трактуются «как есть», без подстановки переменных и тд.

Как и PHP, Perl интерпретирует скаляры, как числа или как строки в зависимости от операции. Все просто:

$int1 = "11" + 22 ;
# ^ строка "11" преобразуется в число,
# после чего выполняется сложение, результат: 33.
$str1 = "11" . 22 ;
# ^ число 22 преобразуется в строку,
# после чего выполняется конкатенация, результат: "1122".

Правила преобразования из строки в число и наоборот тут те же, что и в PHP:

$str1 = 0 . "abc" ;
# ^ результат - "abc", число ноль преобразуется в пустую строку
$int1 = "aaa" + 1 ;
# ^ результат - 1, в строке "aaa" нет цифр
$int2 = "12aaa" + 1 ;
# ^ результат - 13, учитываются только первые цифры строки

Кстати, для объявления длинных строк существуют специальные операторы — q и qq:

# аналогично одинарным кавычкам
$text = q {
Do you have $15 ?
} ;
# аналогично двойным кавычкам
$message = qq {
Hello, $username !
How are you?
} ;

Работа с массивами происходит следующим образом:

#!/usr/bin/perl

$scalar = "bebebebe" ;
($a , $b ) = (1 , 2 ) ; # тоже самое, что $a = 1; $b = 2;
@arr = ("aaa" , 123 , $scalar , $a + $b ) ;
print $arr [ 1 ] . "\n " ;
push @arr , $a ;
print pop (@arr ) . "\n " ;

Здесь мы создаем массив @arr, состоящий из 4-х элементов (строка 5). Затем выводим второй элемент (строка 6). Нумерация элементов начинается с нуля, поэтому для вывода второго по счету элемента используется индекс 1. Затем кладем в конец массива значение переменной $a (функция push, строка 7), и тут же извлекаем и выводим его (функция pop, строка 8).

Обратите внимание, имена массивов начинаются с «собаки», а не доллара (запомнить не сложно — соответствующие символы похожи на первые буквы английских названий типов: $ — scalar, @ — array). При обращении ко второму элементу массива (строка 6) использовался знак доллара, потому что элемент массива является скаляром. По началу это вызывает много путаницы, но вообще все логично.

Еще в этом скрипте мы вызываем функции print и push без скобок. В Perl при вызове функции, везде, где это не вызывает неопределенности, скобки можно опустить.

Для объявления массива, элементами которого являются строки без пробелов, существует специальный оператор — qw:

@arr = qw/aaa bbb ccc/ ;
# аналогично ("aaa", "bbb", "ccc"), только короче

Хэши похожи на массивы, но элементы в хэше не упорядочены. При этом в качестве ключа, по которому производится доступ к элементу, могут использоваться строки.

#!/usr/bin/perl

%hash = ( # при объявлении хэшей и массивов можно
"x" => 12 , # использовать перенос строк
y => 53 , # если в ключе нет спец-символов, кавычки не нужны
"z" => - 10.5 , # запятую на конце можно оставлять
) ;

$hash { "x" } ++; # координата по x теперь равна 13
$hash { y } --; # координата по y теперь равна 52

# выводим координаты
print "x = $hash{x}, y = $hash{y}, z = $hash{z}\n " ;

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

Кстати, переменные $test, @test и %test — это совершенно независимые друг от друга переменные разного типа.

В этом месте я хотел перейти к условным операторам и циклам for/while, но понял, что для одного поста текста и так уже многовато. Между тем за кадром остались многие вопросы:

  • Условные операторы;
  • Циклы for и while;
  • Объявление функций;
  • Работа с потоками и файлами;
  • Строгий синтаксис;
  • Использование готовых модулей и классов.

Об этом я напишу в одной из следующих заметок. Хотелось бы получить хотя бы парочку комментариев на этот пост — интересно/неинтересно, понятно/непонятно и так далее. Кстати, если у вас есть вопросы, связанные с Perl (не обязательно с этим постом) — смело задавайте их в комментариях!

Надеюсь, серия постов о программировании на Perl поможет вам написать ваши первые простенькие скрипты. Со временем скрипты будут становится сложнее, в них станут использоваться новые технологии (ООП, регулярные выражения) и через какое-то время вы обнаружите, что знаете о Perl достаточно, чтобы делиться опытом с другими.

Главная страница » PERL » Циклы и ветвления.

Создание скриптов CGI с помощью PERL.

СОЗДАНИЕ СКРИПТОВ CGI С ПОМОЩЬЮ PERL. В главе 12 вы познакомились с программированием на языке Perl. В это главе вы научитесь использовать Perl для создания скриптов CGI. Коротко говоря, вы получите возможность сочетать ваши знания по языку Perl и CGI, полученные в предыдущих главах. Кроме того, вы узнаете несколько новых приёмов программирования на языке Perl. Как вы уже знаете, можно создать скрипты CGI, используя практически любой язык программирования. Чтобы быть грамотным Web-программистом, вы должны не только знать, как писать програм- мы для WEB, но также необходимо иметь представление о том, какие средства использовать для решения специфических задач. За счёт правильного выбора языка программирования и программных средств в соответствии с вашей задачей, вы можете значительно повысить эф- фективность работы и сэкономив много сил и времени. Когда вы ис- пользуете язык Perl для создания скриптов, можно создать устойчи- вые профессиональные скрипты за относительно короткий промежуток времени. Остаток этой главы посвящен изучению программирования CGI-скриптов на языке Perl. К моменту окончания изучения этой главы вы поймете следующие концепции: ? Perl представляет собой эффективное средство для создания на- дежных скриптов без написания кодов большого объёма, что выгодно отличает его от других языков программирования, таких как C и С++. ? Версия 5 языка Perl добавляет много новых возможностей, таких как поддержка объектно-ориентированных скриптов и усовершенство- вание техники определения области видимости переменных. Почему разработчики используют Perl для создания CGI- скрип- тов? Предыдущие две главы должны были составить у вас представле- ние о том, что такое CGI и почему мощные возможности языка Perl по обработке текстов делают его хорошо приспособленным для разра- ботки CGI-скриптов. Другие причины и пользования разработчиками языка Perl для написания CGI-скриптов заключаются в том, что Perl обеспечивает широкую поддержку взаимодействия с базами данных, обладает переносимостью и обеспечивает безопасность при работе в сетях. Как уже говорилось, Perl представляет собой один из наибо- лее мощных языке программирования для обработки текстов. Скрипты CGI обычно имеют дело с интенсивной обработкой текста: анализом данных, обеспечением доступа к база данных, генерацией HTML-стра- ниц и т. д. Типичный CGI-скрипт, написанный на языке Perl, по своему размеру представляет собой фрагмент программы аналогичного назна- чения, написанной на C++. Как вы увидите дальше в этой главе, Perl обеспечивает поддержку взаимодействия с базами данных. По существу, Perl имеет встроенный менеджер баз данных Perl был пе- ренесен почти что на все популярные вычислительные платформы та- кие как Windows, UNIX, MS, DOS. To обстоятельство, что Perl яв- ляется 6ecплатным, также увеличивает его привлекательность. Пос- кольку Perl не использует указателей, то он является более безо- пасным и надежным языком, чем С и C++. За счет исключения ис- пользования указателей предовращается нарушение доступа к памяти и связанные с этим ошибки. Кроме того используя регулярные выра- жения языка Perl, легко проверить целостность входных данных и отфильтровать всякие escape-последовательности, которые МОГУТ уг- рожать безопасности вашей системы. Наконец, для повышения безо- пасности имеется специальная версия Perl, называемая taintperl, предотвращающая использование каких-либо входных данных в качес- тве системных команд. Дополнительную и информацию о taintperl можно найти на Web-узлах, указанных в конце этой главы. ВЫЗОВ CGI-СКРИПТА На UNIX-системах программисты могут исполнять скрипты, напи- санные на языке Perl, как выполнимые файлы. Иными словами, для них нет необходимости делать что-то специальное для вызова скрип- та. На системах, основанных на DOS или Windows, некоторые серве- ры не исполняют скрипты Perl автоматически. В этом случае вам придется писать пакетный файл, который вызывает команды Perl для запуска скрипта. Для некоторых систем придется подробнее познако- миться (. документацией по вашему НТTР-серверу относительно за- пуска скриптов Perl. Большинство серверов HTTP предполагает, что скрипты CGI находятся в каталоге под названием cgi-bin. В этом случае можно вызвать скрипт с помощью URL, подобно следующему: http://your-domain/cgi-bin/your-script Примечание: В URL задан каталог cgi-bin, но в действительности скрипт может находиться где угодно в системе. Вы должны опреде- лить его расположение при установке сервера HTTP. ВЫЗОВ СGI-СКРИПТА В СИСТЕМЕ UNIX Если вы поместили ваш скрипт в каталог cgi-bin и сделали его выполнимым, то пользователь может вызвать скрипт, непосредствен- но используя URL. Однако необходимо выполнить несколько шагов. В первую очередь, в начало скрипта необходимо поместить строку, ко- торая идентифицирует файл как программу на языке Perl: #!/usr/bin/perl Примечание: Вы должны будете указать в этой строке путь, завися- щий от того, где установлен Perl на вашей системе. Далее необходимо сделать скрипт выполнимым, используя команду chmod: chmod +x your-srcipt ВЫЗОВ СКРИПТА НА ЯЗЫКЕ PERL ИЗ DOS И WINDOWS В DOS или Windows скрипты Perl сами по себе не являются вы- полнимыми самостоятельными программами. Вместо этого необходимо запустить исполнимую программу PERL.EXE, включая имя скрипта на языке Perl в командной строке. Для упрощения этого процесса мож- но создать ВАТ-файл для каждого вашего скрипта, который запус- кает PERL. ЕХЕ с соответствующим файлом, содержащим скрипт. Нап- ример, предположим, что ваш ВАТ-файл HELLO.ВАТ содержит следую- щие команды: @echo off perl Hello.pl %1 %2 %3 %4 %5 %6 %7 %8 %9 Также предположим, что скрипт Perl Hello.PL содержит следую- щие инструкции: print "Hello, args are "@ARGV"\n"; Как можно видеть, ВАТ-файл просто запускает программу PERL.EXE с указанием скрипта Hello.PL в качестве входной коман- дной строки. Если вы запустите скрипт на языке Perl из Web-серве- ра, то обнаружите, что большинство HTTP-серверов распознают скрипты на языке Perl (например, как это делает FolkWeb- сервер), так что нет необходимости в использовании ВАТ-файла. Иными слова- ми, если вы используете HTTP-сервер наподобие FolkWeb, вам нет надобности делать что-то специальное для вызова CGI-скрипта на языке Perl. В противном случае может потребоваться создать ВАТ-файл. Если ваша программа-сервер нуждается в ВАТ-файле для выпол- нения скрипта на языке Perl, вы должны поместить ВАТ-файл (такой как HELLO.ВАТ) в каталог cgi-bin и туда же - скрипт Perl (Hello.PL). СОЗДАНИЕ ТЕКСТА И HTML-ДОКУМЕНТА С ИСПОЛЬЗОВАНИЕМ ЯЗЫКА PERL Создание текстовых документов с использованием языка Perl представляет собой тривиальную задачу. Вам только необходимо удостовериться, что вы поместили правильный НТМL заголовок в на- чале текстового документа. Например, следующий скрипт создает простой текстовый документ, содержащий сообщение Hello, world: print "Content-type: text/plain\n\n"; print "Hello, world\n"; Создание текстовых документов HTML также очень легко. Напри- мер, в следующем фрагменте текста создается простой документ HTML: print Hello, world HTML Эти примеры больше походят на исходные коды HTML, чем на программу на языке Perl. Действительно, если вы удалите нес- колько строк, вы будете иметь HTML-файл. Эта иллюстративная прог- рамма использует свойства языка Perl, которые не были рассмотре- ны в предыдущей главе, но они достаточно просты для понимания. Строка представляет собой просто нес- колько строк литералов. Perl обрабатывает как строку в двойных кавычках. Поскольку делает ис- ходный код на языке Perl легким для чтения, то использование та- кой конструкции является идеальным для создания HTML-документов. Используя конструкцию, скрипт на языке Perl мо- жет не иметь символов цитирования и символов новой строки, и не должен содержать функций printf. Конструкция ши- роко используется в рассматриваемых далее в этой главе примерах. ДОБАВЛЕНИЕ В ДОКУМЕНТ ДИНАМИЧЕСКИХ СВОЙСТВ Если бы возможности CGI-скриптов ограничивались созданием статических форм, то это было бы грустно. Настоящая сила CGI сос- тоит в придании Webстраницам динамики. В главе 11 вы рассматрива- ли программу на языке C++, которая создает скрипт, выводящий на экран значения переменных окружения. Следующий скрипт на языке Perl решает идентичную задачу. Тем не менее, вы убедитесь, нас- колько проще выглядит программа на языке Perl, чем аналогичная С++ версия, показанная в главе 11: print Environment Variables: for $env (sort keys %ENV) { print "
  • $env is $ENV{$env}
    "; } print " \n" Этот пример создает статический заголовок, и затем выводит значения переменных окружения скрипта, используя форматированный HTML-документ. Скрипт показывает, как использовать конструкцию совместно с традиционной функцией print. ДОСТУП К СТРОКЕ ЗАПРОСОВ В главе 11 вы видели, что простым способом передачи данных CGI в скрипт является использование строки запросов. Броузер пе- редает данные HTTP-серверу как часть URL. В свою очередь сервер рассматривает все, что следует за знаком вопроса (?) в URL, как строку запроса. CGI-скрипт может получить доступ к строке запросов двумя способами. Либо сервер передает строку запросов скрипту, ис- пользуя аргументы командной строки, либо сервер присваивает зна- чение строки запросов переменной окружения QUERY_STRING. Напри- мер, можно возвратиться к рассмотренному выше скрипту, который выводит на экран значения переменных окружения, и вызвать скрипт, используя строку запросов. ДЕКОДИРОВАНИЕ ФОРМ HTML С ИСПОЛЬЗОВАНИЕМ МЕТОДА GET. Как вы увидели, использование подсказки ISINDEX для созда- ния одиночного запроса достаточно просто. Но для получения от пользователя больше чем одного значения необходимо использовать формы. Следующий скрипт на языке Perl генерирует форму. Используя метод GET, скрипт дает команду броузеру послать значения запроса как часть URL, так же как при использовании ISINDEX. Разница меж- ду использованием GET и ISINDEX состоит в том, что при использо- вании метода GET броузер может соединить несколько величин полей в одну строку запросов, разделяя поля с помощью амперсанда (&). Для того чтобы скрипт мог определять значения полей, броузер включает имена полей в строку запроса. Например, если база дан- ных содержит три поля (имя, возраст и день рождения) с такими значениями (Bob, 27, 11-1-68), то строка запросов будет содер- жать значения полей в следующем формате: . В следующем примере скрипт декодирует поля и выводит на экран их значения с помощью созда- ния HTML-формы: ($cgi_bin, $cgi_script) = ($0 =~ m:(.*)(.*):); $query = $ENV{QUERY_STRING}; if ($query eq "") { # сгенерируем форму print
    A checkBox.

    A radio button set.
    1
    2
    3

    A data entry field

    Send the data.

    FORM } else { # распечатаем результаты print "Content-type: text/html\n\n"; print " \n"; print " GET Form Result \n" print " \n"; print "Your query values:

    \n"; @fields = split("&", $query); forech (@field) { Switch: { /^check=(.*)/ && do { $check = $1; last Switch; }; /^button=(.*)/ && do { $button = $1; last Switch; }; /^field=(.*)/ && do { $field = $decode(1); last Switch; }; } } print "Check Box: $check
    \n"; print "Radio Button: $button
    \n"; print "Data Field:", &html($field), "
    \n"; print " \n"; } sub decode{ local ($value) = @_; $value =~ s/\+/ /g; $value =~ s/%({2})/pack("C",hex($1))/eg; return $value; } sub html { local ($value) = @_; $value =~ s//>/g; return $value" } Обратите внимание на первую строку скрипта: ($cgi_bin, $cgi_script) = ($0 =~ m:(.*)(.*):); Это выражение выглядит похожим на аналогичное выражение в предыдущем примере. Однако в данном случае скрипт разделяет путь на каталог и имя файла. В этом примере один и тот же скрипт соз- дает форму и обрабатывает ее вывод, что достаточно нетрудно вы- полнить. Такой способ рекомендуется для обработки форм, потому что концентрирует всю обработку в одном месте. Скрипт определяет, создавать ли форму или обработать запрос, в зависимости оттого, поступил ли запрос от пользователя. Для об- работки строки запросов скрипт разделяет запрос на поля, ис- пользуя функцию split. Далее скрипт сравнивает поля запроса с ожидаемыми именами полей. Рассмотрим следующий пример: forech (@field) { Switch: { /^check=(.*)/ && do { $check = $1; last Switch; }; Обычная форма цикла foreach включает переменную {$VAR). Если цикл foreach опускает эту переменную, то Perl использует перемен- ную по умолчанию $_. Аналогично, оператор регулярного выражения обычно выглядит следующим образом $VAR=~/PATTERN/. Если перемен- ная в выражении опущена, Perl использует $_ как переменную по умолчанию, в результате чего цикл и регулярное выражение соответ- ствуют друг другу. Однако если слишком полагаться на переменные по умолчанию, то код на языке Perl может получиться неясным. В данном же случае использование переменных, определенных по умол- чанию, делает код более коротким и лучше читаемым. Далее обратите внимание на регулярное выражение, имеющее форму /^field=(. *)/. Данное выражение указывает на необходи- мость начать поиск от начала строки, что предотвращает совпаде- ния в середине имени другого поля. Иными словами, имя поля и знак равенства (=) должны соответствовать сами себе. Остающаяся часть регулярного выражения соответствует значению поля и извлекает его в переменную $1. Поскольку $1 представляет собой временную пере- менную, то скрипт копирует ее в переменную с именем для каждого поля. Скрипт использует подпрограмму decode для декодирования символов из полей, которые были закодированы броузером. Регуляр- ные выражения, используемые подпрограммой декодирования, рассмат- ривались в предыдущем примере. Наконец, скрипт использует подпрограмму html, чтобы закоди- ровать значения данных для вывода их в тексте HTML. Скрипт может послать большую часть текста броузеру в виде HTML-документа без выполнения какой-либо обработки. Однако поскольку HTML ис- пользует угловые скобки () для кодирования НТМL-входов, скрипт должен закодировать эти скобки, используя последовательности HTML < и >. ДЕКОДИРОВАНИЕ HTML-ФОРМ С ПОМОЩЬЮ МЕТОДА POST Следующий скрипт очень напоминает только что обсуждавшийся, за исключением того, что данный скрипт использует метод POST для посылки данных формы скрипу CGI. Метод POST дает директиву броу- зеру послать данные формы, используя стандартный вход скрипта, а не строку запросов. Полезность метода POST заключается в том, что он может обрабатывать большие объемы данных, тогда как метод GET ограничен пространством переменной сервера, а также длиной URL броузера. Для чтения данных со стандартного ввода скрипт может выз- вать функцию sys-read с нужным числом байт. Размер строки запро- са в байтах содержится в переменной окружения CONTENT_LENGTH. После того как скрипт прочел строку запросов, дальнейшая обработ- ка данных оказывается очень похожей на рассмотренную в предыду- щем примере. Для того чтобы сделать, этот скрипт более коротким, обработка строки запросов осуществляется с помощью несколько бо- лее сложного подхода: ($cgi_bin, $cgi_script) = ($0 =~ m:(.*)(.*):); $content_length = $ENV(CONTENT_LENGTH); if (!definet($query) || $query eq "") { # сгенерируем форму print



  •