Большой архив статей, книг, документации по программированию, вебдизайну, компьютерной графике, сетям, операционным системам и многому другому
 
<Добавить в Избранное>    <Сделать стартовой>    <Реклама на сайте>    <Контакты>
  Главная Документация Программы Обои   Экспорт RSS E-Books
 
 

   Интернет технологии -> Perl -> Практический Перл для начинающего


Практический Перл для начинающего

Александр Боровский

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

Сразу нужно пояснить, для кого это все написано. Если Ваш сервер работает на платформе UNIX, то это я должен читать Вашу статью. У меня же установлен Windows NT workstation 4.0 (RUS) плюс Service Pack 3. Когда пришло время сделать из компьютера WEB-сервер, я было кинулся ко встроенным Службам узла WEB, но быстро понял, что это мне не нравится (почему ?). И тут один добрый человек посоветовал поставить Xitami WEB Server от iMatix Corporation (www.imatix.com), который и стоит по сей день.

Что касается самого Перла, то здесь несколько сложнее. Покопавшись по различным Перловым серверам (www.perl.org , www.perl.com ) я узнал, что версий Перла настолько много, что выбрать что-нибудь конкретное довольно сложно. При этом каких-нибудь вразумительных рекомендаций по поводу выбора той или иной версии нигде нет. Перепробовав почти все версии для Windows, я остановил свой выбор на Active Perl (www.ActiveState.com).

Человеку, избалованному всякими Виндовозами и Дельфями, писать программы на Перл довольно непривычно, поэтому настоятельно рекомендую сразу установить Perl Builder. Взять его можно на www.solutionsoft.com. Там лежала тридцатидневная Демо версия.

Ну, думаю, пора переходить непосредственно к делу. В общем случае, скрипт на Перл, как и любая другая программа, работает так:

  1. получает данные
  2. обрабатывает данные
  3. выдает результаты

Передать данные скрипту можно двумя методами - GET и POST. Разница между ними в том, что при использовании GET данные постоянно болтаются в строке адреса браузера, напимер:

httр://treagraf.tasur.edu.ru/cgi-bin/price.pl?Category=POWER&Description=varta

В этом случае скрипт B_price.pl берет данные в переменной окружения QUERY-STRING.

$data=$ENV{'QUERY_STRING'};

При использовании метода POST данные передаются на стандартный вход скрипта. Длинна блока данных берется в переменной CONTENT_LENGTH:

read(STDIN,$data,$ENV{'CONTENT_LENGTH'});

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

Стандартным соглашением служит замена пробелов знаками плюс и затем кодировка оставшихся недопустимых символов с помощью ASCII-кодов в шестнадцатиричной форме, перед которыми ставится знак (%). Пример:

http://treagraf.tasur.edu.ru/cgi-bin/B_price.pl?Category=%C2%E8%E4%E5%EE&Description=%E0%E1%E2%E3

Это значит:

http://treagraf.tasur.edu.ru/cgi-bin/B_price.pl?Category=Видео&Description=абвг

Декодировать строку запросов в первый раз лучше самому. На вопрос "а как?" есть множество ответов, переписывать которые нет смысла. Приведу лишь короткий пример:

Заменяем знаки (+) на пробелы

$query = ~ s/\+/ /g;

Потом заменяем все сочетания знака (%), после которого следуют шестнадцатиричные цифры, на соответствующий символ ASCII

$query  =~ s/%([0-9A-H]{2})/pack('C', hex($1))/eg;

Я пользуюсь тем, что предлагает Perl Builder:

#! E:\perl5\bin\perl

&GetFormInput;                        # вызов подпрограммы получения данных


$Category = $field{'Category'};       # получаем  данные из поля Category
$Description = $field{'Description'}; # получаем  данные из поля Description
$Page = $field{'Page'};               # получаем  данные из поля Page

В конце скрипта помещаем подпрограмму "прозрачного" чтения данных.

sub GetFormInput {

	(*fval) = @_ if @_ ;

	local ($buf);
	if ($ENV{'REQUEST_METHOD'} eq 'POST') {
		read(STDIN,$buf,$ENV{'CONTENT_LENGTH'});
	}
	else {
		$buf=$ENV{'QUERY_STRING'};
	}
	if ($buf eq "") {
			return 0 ;
		}
	else {
 		@fval=split(/&/,$buf);
		foreach $i (0 .. $#fval){
			($name,$val)=split (/=/,$fval[$i],2);
			$val=~tr/+/ /;
			$val=~ s/%(..)/pack("c",hex($1))/ge;
			$name=~tr/+/ /;
			$name=~ s/%(..)/pack("c",hex($1))/ge;

			if (!defined($field{$name})) {
				$field{$name}=$val;
			}
			else {
				$field{$name} .= ",$val";
				
				#if you want multi-selects to goto into an array change to:
				#$field{$name} .= "\0$val";
			}


		   }
		}
return 1;
}

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

И, наконец, Вам нужно выдать какие-то результаты броузеру клиента, причем так, чтобы броузер правильно их отобразил. То есть, выдавать результаты нужно в HTML. Это делается просто: (тоже можно по-разному)

print 'Content-type: text/html', "/n/n";          #обязательная строка
print '

В поле Category Вы ввели: ', $Category, '

',"\n"

Все это касается скриптов, получающих данные из формы на странице HTML. При этом страница с формой - отдельно, скрипт - отдельно. Можно сделать красивее и удобнее: объединить страницу и скрипт в единое целое. Для этого скрипт пишется по схеме:

  1. При первом запуске скрипт рисует HTML страницу с формой и ссылкой в тэге ACTION на самого себя. Первый запуск определяется по отсутствию входных данных.
  2. Если входные данные есть, то получаем их, обрабатываем и выдаем результаты.

Пример:

#! E:\perl5\bin\perl

if (($ENV{'QUERY_STRING'} eq '') or ($ENV{CONTENT_LENGTH}=0) ) 
  { # генерируем страницу с формой }
        else 
            {# получаем данные, обрабатываем и выдаем результат}

Гостевая книга

Общий алгоритм работы гостевой книги таков:

1. Если посетитель хочет сделать запись в книгу, то
1.1 Получаем данные
1.2 Записываем их в файл или в базу данных
1.3 Говорим спасибо на HTML и предлагаем почитать другие записи
2. Если посетитель хочет почитать записи в книге, то
2.1 Читаем записи из файла или из базы данных
2.2 Выводим их красиво в HTML

Для удобства восприятия я оформил пункты 1 и 2 отдельными скриптами add_guestbook.pl и read_guestbook.pl соответственно. Сообщения гостевой книги хранятся в текстовом файле построчно, т.е. на каждую запись - строка. Так сделано для удобства чтения этого файла. Пример одной записи:

Sat Dec 5 13:31:20 1998&Наташа&студентка&Good&Для начала хорошо. Успехов на данном поприще Вам, Александр!&нету@пока&194.226.60.34

Вот описание полей рассматриваемой гостевой книги.
Name - имя, фамилия, отчество, кличка - на усмотрение посетителя
Work - профессия, род занятий
RadioButton - три кнопки: понравилось (Good), не понравилось (Bad), пофигу (Different)
Text - text box комментариев и примечаний
Email - обратный адрес

add_guestbook.pl - запись в книгу

#! e:\perl5\perl
# Первая строка, как обычно

require "ssi-pl.pl";
# Я использую навигационную панель в виде SSI-включения. 
# Для этого используется модуль ssi-pl.pl

if (($ENV{'QUERY_STRING'} eq '') or ($ENV{CONTENT_LENGTH}=0) ) 
  { 
# Если нет входных данных, то генерируем страницу с формой

print <

<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<meta name="GENERATOR" content="Microsoft FrontPage 3.0">
<title>Книга жалоб и предложений</title>
</head>

<body background="../images/background_new.jpg">
<div align="left">

<table border="0" width="630" height="49">
  <tr>
    <td width="200" height="45"></td>
    <td width="430" height="45"><p align="center"><img src="../images/guestbook.GIF"
    alt="Книга жалоб" WIDTH="258" HEIGHT="60"></td>
  </tr>
</table>
</div><div align="left">

<table border="0" width="630" height="53" cellspacing="0" cellpadding="0">
  <tr>
    <td width="200" height="260" valign="top">
  
    <p align="center">
    
HTML
DoInclude("_menu.htm"); # Это SSI-включение навигационной панели.

print <<HTML;

    </p>
    <p align="left"> </td>
    <td width="10" height="53" valign="top"></td>
    <td width="410" height="53" valign="top"><table border="1" width="100%" cellspacing="0"
    cellpadding="0">
      <tr>
        <td width="100%"><form name="GuestBook" method="POST" action="add_guestbook.pl">
          <div align="left"><p><small>Я, <input type="text" name="Name" size="20"></small>, <small>по
          профессии простой </small><input type="text" name="Work" size="20">, <small>посетив
          данный сервер и ознакомившись с представленными
          на нем материалами, хочу выразить свои чувства и
          эмоции следующими приличными словами:</small></p>
          </div><div align="left"><p><small> </small><input type="radio" value="Good" checked
          name="RadioButton"><small>мне понравилось :-)</small></p>
          </div><div align="left"><p><small> </small><input type="radio" name="RadioButton"
          value="Bad"><small>мне не понравилось :-( </small></p>
          </div><div align="left"><p> <input type="radio" name="RadioButton" value="Different"><small>мне
          пофигу :-| </small></p>
          </div><div align="left"><p><small>В дополнение к сказанному хочу
          так же сказать: </small></p>
          </div><div align="left"><p><textarea rows="4" name="Text" cols="30"></textarea></p>
          </div><div align="left"><p><small>Прошу принять к рассмотрению
          мое заявление и незамедлительно принять меры.
          Решение по моему заявлению направить письменно
          на мой электронный адрес </small><input type="text" name="Email"
          size="20"><small>.</small></p>
          </div><div align="center"><center><p><input src="../images/send.JPG" name="Send"
          alt="Послать" border="0" type="image" WIDTH="53" HEIGHT="21">    <a
          href="read_guestbook.pl"><img src="../images/read.jpg" alt="Почитать" border="0"
          WIDTH="63" HEIGHT="21"></a></p>
          </center></div>
        </form>
        </td>
      </tr>
    </table>
    </td>
    <td width="10" height="53" valign="top"></td>
  </tr>
</table>
</div>
</body>
</html>
HTML
die;
}

# Теперь получаем входные данные.

&GetFormInput;


$Name = $field{'Name'} ;	 
$Work = $field{'Work'} ;	 
$RadioButton = $field{'RadioButton'} ;	 
$Text = $field{'Text'} ;	 
$Email = $field{'Email'} ;	 
$Send = $field{'Send'} ;	 # это поле не используется

# Проверяем, заполнены ли обязательные поля.
# Если нет - генерируем HTML страницу с просьбой заполнить нужные поля.

if ($Name eq '' || $Email eq '' || $Text eq '')
{
print <<HTML;
Content-type: text/html

<html>

<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<meta name="GENERATOR" content="Microsoft FrontPage 3.0">
<title>Книга жалоб и предложений - ошибка</title>
</head>

<body background="../images/background_new.jpg">
<div align="left">

<table border="0" width="630" height="49">
  <tr>
    <td width="200" height="45"></td>
    <td width="430" height="45"><p align="center"><img src="../images/guestbook.GIF"
    alt="Книга жалоб" WIDTH="258" HEIGHT="60"></td>
  </tr>
</table>
</div><div align="left">

<table border="0" width="630" height="53" cellspacing="0" cellpadding="0">
  <tr>
    <td width="200" height="260" valign="top"><p align="center">
    
HTML
DoInclude("D:/InetPub/wwwroot/_menu.htm"); 
print <<HTML;


    </p>
    <p align="left"> </td>
    <td width="10" height="53" valign="top"></td>
    <td width="410" height="53" valign="top"><p align="left"><small>Вы не указали
    свое имя, E-mail, либо не заполнили сам текст Вашего
    отзыва. Вернитесь, пожалуйста, на страницу формы
    и заполните требуемые поля.</small></p>
    <p align="center"><a href="add_guestbook.pl">Назад</a> </td>
  </tr>
</table>
</div>

<table>
  <tr>
    <td width="10" height="53" valign="top"></td>
  </tr>
</table>
</body>
</html>
HTML
} 
 else # все данные правильно введены
{

# Если все поля заполнены правильно, то начинаем их обрабатывать. 

$Text=~tr/\r\n/  /; #заменяем перевод строки на пробел
# Если в текстовом поле формы (text box) посетитель нажимал Enter,
# то нужно убрать символы перевода строки, чтобы можно было записать
# все поля формы в одну строку файла.

if ($Work eq '') {$Work=' '}; #если пусто - то пробел
# Если поле не заполнено, то оно равно пробелу.

$Name=~s/&/ /g;
$Work=~s/&/ /g;
$Text=~s/&/ /g;
$Email=~s/&/ /g;
# Если посетитель использовал символ &, то заменяем его на пробел,
# поскольку этот символ мы будем использовать для разделения наших полей в файле.

open(OutFile, ">>guestbook.txt") || die;
# Открываем файл для добавления.

$Time=localtime;       #получаем время
# Получаем время заполнения гостевой книги.

$line=join('&', $Time, $Name, $Work, $RadioButton, $Text, $Email, $ENV{REMOTE_HOST});
# И, наконец, слепляем все поля формы в одну строку. На всякий случай добавляем в конце
# IP адрес посетителя, взятый из переменных окружения.

print OutFile "$line\n";
close OutFile;
# Записываем полученную строку в файл и закрываем его.

# Осталось только сказать посетителю спасибо.

# выводим сообщение о успехе

print "Content-type: text/html\n\n";
print "<html>\n" ;
print "\n" ;
print "<head>\n" ;
print '<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">'."\n" ;
print '<meta name="GENERATOR" content="Microsoft FrontPage 3.0">'."\n" ;
print "<title>Книга жалоб и предложений</title>\n" ;
print "</head>\n" ;
print "\n" ;
print '<body background="../images/background_new.jpg">'."\n" ;
print '<div align="left">'."\n" ;
print "\n" ;
print '<table border="0" width="630" height="49">'."\n" ;
print "  <tr>\n" ;
print '    <td width="200" height="45"></td>'."\n" ;
print '    <td width="430" height="45"><p align="center">';
print '<img src="../images/guestbook.GIF" alt="Книга жалоб" WIDTH="258" HEIGHT="60"></td>'."\n" ;
print "  </tr>\n" ;
print "</table>\n" ;
print '</div><div align="left">'."\n" ;
print "\n" ;
print '<table border="0" width="630" height="53" cellspacing="0" cellpadding="0">'."\n" ;
print "  <tr>\n" ;
print '    <td width="200" height="260" valign="top"><p align="center">'."\n" ;

DoInclude("D:/InetPub/wwwroot/_menu.htm"); 
print '    <p align="left"> </td>'."\n" ;
print '    <td width="10" height="53" valign="top"></td>'."\n" ;
print '    <td width="410" height="53" valign="top"><p align="center"><small>Ваши данные'."\n" ;
print "    приняты. Спасибо.</small></p>\n" ;
print '    <p align="center"><a href="read_guestbook.pl">';
print '<img src="../images/read.jpg" alt="Почитать" border="0" WIDTH="63" HEIGHT="21"></a> </td>'."\n" ;
print "  </tr>\n" ;
print "</table>\n" ;
print "</div>\n" ;
print "\n" ;
print "<table>\n" ;
print "  <tr>\n" ;
print '    <td width="10" height="53" valign="top"></td>'."\n" ;
print "  </tr>\n" ;
print "</table>\n" ;
print "</body>\n" ;
print "</html>\n" ;
}

# Не забываем подпрограмму разбора данных из формы.
sub GetFormInput {

	(*fval) = @_ if @_ ;

	local ($buf);
	if ($ENV{'REQUEST_METHOD'} eq 'POST') {
		read(STDIN,$buf,$ENV{'CONTENT_LENGTH'});
	}
	else {
		$buf=$ENV{'QUERY_STRING'};
	}
	if ($buf eq "") {
			return 0 ;
		}
	else {
 		@fval=split(/&/,$buf);
		foreach $i (0 .. $#fval){
			($name,$val)=split (/=/,$fval[$i],2);
			$val=~tr/+/ /;
			$val=~ s/%(..)/pack("c",hex($1))/ge;
			$name=~tr/+/ /;
			$name=~ s/%(..)/pack("c",hex($1))/ge;

			if (!defined($field{$name})) {
				$field{$name}=$val;
			}
			else {
				$field{$name} .= ",$val";
				
				#if you want multi-selects to goto into an array change to:
				#$field{$name} .= "\0$val";
			}


		   }
		}
return 1;
}

Вот и все. Пример работы описанного скрипта можно посмотреть на http://treagraf.tasur.edu.ru/cgi-bin/add_guestbook.pl

read_guestbook.pl - чтение книги

#! e:\perl5\perl
# Первая строка, как обычно

require "ssi-pl.pl";
# Я использую навигационную панель в виде SSI-включения. 
# Для этого используется модуль ssi-pl.pl

open(InFile, "guestbook.txt") || die;
# Открываем файл с записями гостевой книги.

@lines=<InFile>;
# Читаем строки в массив.

# Выдаем шапку HTML страницы.
print <<HTML;
Content-type: text/html

<html>

<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<meta name="GENERATOR" content="Microsoft FrontPage 3.0">
<title>Книга жалоб и предложений - нам пишут</title>
</head>

<body background="../images/background_new.jpg">
<div align="left">

<table border="0" width="630" height="49">
  <tr>
    <td width="200" height="45"></td>
    <td width="430" height="45"><p align="center"><img src="../images/guestbook.GIF"
    alt="Книга жалоб" WIDTH="258" HEIGHT="60"></td>
  </tr>
</table>
</div><div align="left">

<table border="0" width="630" height="53" cellspacing="0" cellpadding="0">
  <tr>
    <td width="200" height="260" valign="top"><p align="center"><small>
    
HTML
DoInclude("D:/InetPub/wwwroot/_menu.htm"); 
print <<HTML;
    </p>
    <p align="left"> </td>
    <td width="10" height="53" valign="top"></td>
    <td width="410" height="53" valign="top"><p align="center">Нам пишут:</p>
    <table border="0" width="100%" cellspacing="0" cellpadding="0">
HTML

# Теперь выводим записи в невидимой (в смысле, рамка не видима) таблице.
# Чтобы свежие записи отображать первыми, обрабатываем массив строк с конца.

for ($i=$#lines; $i>=$[; $i--) #обрабатываем строки файла с конца
{

# Разделяем строку на части
@item=split('&', $lines[$i]); #разделяем на части

# Теперь заменяем HTML тэги в записи (на случай какого-нибудь хитрого юзера)
foreach (@item)
{
	$_=~s/</</g;
	$_=~s/>/>/g;
}

# Приступаем непосредственно к выводу записей в HTML
print "<tr>\n";
print '<td width="100%"><dl>'."\n";

# В зависимости от поля, где посетителю предлагался выбор понравилось - не понравилось,
# рисуем картинку с веселой или грустной мордочкой соответственно. В качестве ALT тэга
# картинки пропишем IP адрес посетителя.
print '<dt><img src="../images/'.$item[3].'.gif" width="31" height="31" alt="';
priny $item[6].'" align="absbottom"'."\n";

# Выводим остальные поля.
print 'align="absmiddle"><small>'.'   '.$item[4]."</small></dt>\n";
print '<dt><small>'.$item[1].',  '.$item[2]."</small></dt>\n";
print '<dt><a href="mailto:'.$item[5].'"><small>'.$item[5].'</small></a></dt>'."\n";
print '<dt><small>'.$item[0]."</small></dt>\n";
print "</dl>\n";
print "</td>\n";
print "</tr>\n";
}

# Осталось вывести окончание HTML 
print <<HTML;

    </table>
    </td>
    <td width="10" height="53" valign="top"></td>
  </tr>
</table>
</div>
</body>
</html>
HTML

close InFile;
# Закрываем файл с записями гостевой книги.

Вот и все. Пример работы смотрите на http://treagraf.tasur.edu.ru/cgi-bin/read_guestbook.pl


 

 
Интересное в сети
 
10 новых программ
CodeLobster PHP Edition 3.7.2
WinToFlash 0.7.0008
Free Video to Flash Converter 4.7.24
Total Commander v7.55
aTunes 2.0.1
Process Explorer v12.04
Backup42 v3.0
Predator 2.0.1
FastStone Image Viewer 4.1
Process Lasso 3.70.4
FastStone Image Viewer 4.0
Xion Audio Player 1.0.125
Notepad GNU v.2.2.8.7.7
K-Lite Codec Pack 5.3.0 Full


Наши сервисы
Рассылка новостей. Подпишитесь на рассылку сейчас и вы всегда будете в курсе последних событий в мире информационных технологий.
Новостные информеры. Поставьте наши информеры к себе и у вас на сайте появится дополнительный постоянно обновляемый раздел.
Добавление статей. Если вы являетесь автором статьи или обзора на тему ИТ присылайте материал нам, мы с удовольствием опубликуем его у себя на сайте.
Реклама на сайте. Размещая рекламу у нас, вы получите новых посетителей, которые могут стать вашими клиентами.
 
Это интересно
 

Copyright © CompDoc.Ru
При цитировании и перепечатке ссылка на www.compdoc.ru обязательна. Карта сайта.
 
Rambler's Top100