Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Программирование скриптов на Perl'e (Выпуск №9)


Служба Рассылок Subscribe.Ru проекта Citycat.Ru

Программирование скриптов на Perl'e (выпуск ).


Здравствуйте дорогие мои подписчики.


Сегодня в выпуске:




Несколько слов перед началом


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

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

А теперь мы перейдем непосредственно к изучению Perl'а.   И сегодняшние темы:

  • Perl для начинающих - Операторы для работы со строками
  • CGI-программирование - Гостевая книга




    Perl для начинающих - Операторы для работы со строками


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

    chomp список
    chomp переменная

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

    chop список
    chop переменная

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

    chr число
    Возвращает символ из ASCII-таблицы с кодом number.   Например, chr(65) возвратит символ 'A'.

    index строка, подстрока
    index строка, подстрока, позиция

    Возвращает позицию первого вхождения "подстроки" в "строке" считая от заданной "позиции".   Если параметр "позиция" не задан, то сравнение строк ведется от начала "строки".

    join выражение, список
    Возвращает строку, в которой все элементы "списка" соединены "выражением".   Например, join (">>", ("a","b","c")) возвратит строку "a>>b>>c".

    lc строка
    Возвратит строку, где все символы прописные.   Например, lc ("ABCD") возвратит "abcd".

    lcfirst строка
    Возвратит строку, в которой только первый символ прописной.   Например, lcfirst ("ABCD") возвратит "aBCD".

    length строка
    Возвращает длину строки.

    rindex строка, подстрока
    rindex строка, подстрока, позиция

    То же, что и index (смотрите выше), но возвращает позицию последнего вхождения.

    split
    split /шаблон/
    split /шаблон/, строка
    split /шаблон/, строка, предел

    Разбивает строку на части, принимая за границу значение параметра "шаблон".   Например, ($a, $b, $c) = split (/::/, "1::2::3") присвоит переменным $a, $b, $c значения "1", "2", "3" соответственно.   Если же результат используется в скалярном контексте, то функция возвращает количество найденных таким образом элементов.

    substr строка, смещение, длина
    Возвращает часть строки, как определено параметрами "смещение" и "длина".   Если "длина" не указана, возвращается все, что находится на промежутке от "смещения" до конца строки.   Отрицательные значения "смещения" могут использоваться для сканирования с правого края строки.

    uc строка
    То же самое, что и lc (смотрите выше), но все символы заглавные.

    ucfirst строка
    То же самое, что lcfirst (смотрите выше), но символ заглавный.

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

    Пример 1: изменение значения строки

    Очень часто Вам, возможно, понадобится изменять части строк - как правило, где-то в середине строки.   Когда перед Вами станет такая задача, то смело можете воспользоваться функцией substr().   Обычно эта функция используется для получения строки из существующей строки - на основании трех параметров - исходной строки, смещения, которое есть начало новой строки и длины новой строки.

            $firstVar=substr("0123BBB789", 4, 3);
            print "firstVar=$firstVar\n";
    
        Программа напечатает:
    
            firstVar = BBB
    
    Применение данной функции становится гораздо более интересным, когда Вы используете ее слева от оператора присваивания:
            $firstVar="0123BBB789";
            substr($firstVar, 4, 3)="AAA";
            print "firstVar=$firstVar\n";
    
        Программа напечатает:
    
            firstVar=0123AAA789
    
    Пример 2: поиск строки

    Другая интересная задача, которую Вы можете решить с помощью строковых функций - это поиск заданной подстроки в строке.   Например, у Вас есть полное имя файла, включая путь: "/root/temp/data.dat", а Вам нужно получить из него только имя файла.   Вы можете это сделать, найдя последний слеш (символ '/'), а за тем применив функцию substr().

            $pathName="/root/temp/data.dat";
            $position=rindex($pathName, "/")+1;
            $fileName=substr($pathName, $position);
            print "$fileName\n";
    
        Программа напечатает:
    
            data.dat
    
    Мы не указали здесь третий параметр функции substr() - длину, - это потому что нам нужно взять подстроку до конца исходной строки.

    На этом позвольте на сегодня закончить.




    CGI-программирование - Гостевая книга


    Скоро Новый Год, а что такое Новый Год?   Новый Год - это веселье, праздник, гости.   А что нужно гостям?   Гостям нужна гостевая книга и именно в Новый Год :-)

    И сегодня мы поговорим о создании гостевых книг.

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

    В принципе функций не так уж и много:

  • добавление новой записи;
  • просмотр оставленных записей.
    и все, ну в основном.

    Для начала напишем два HTML-документа: для добавления записи и для просмотра оставленных записей.

    Файл guestadd.html

    <HTML>
    <HEAD>
    <META http-equiv="Content-Type" content="text/html; charset=windows-1251">
    <TITLE>Гостевая книга : Добавление записи</TITLE>
    </HEAD>
    <BODY BGCOLOR="#C5BC9B" TEXT="#000000" LINK="#0000FF" VLINK="#800080" ALINK="#FF0000">
    <TABLE WIDTH=780 HEIGHT=420 BORDER=1 ALIGN="CENTER" CELLPADDING=10 CELLSPACING=0 BGCOLOR="#F6E9C0">
      <TR VALIGN="TOP">
        <TD>
        Добро пожаловать в нашу гостевую книгу.   На этой странице Вы можете добавить свой отзыв о
        нашем сайте в книгу, а нажав <A HREF="guestview.html">сюда</A>, Вы cможете просмотреть
        другие отзывы, оставленные ранее.
        <P><BR>
        <FORM ACTION="/cgi-bin/guest.cgi" NAME="RecordForm" METHOD="POST" TARGET="_blank">
          <INPUT TYPE="HIDDEN" NAME="record" VALUE="add">
          <table border=0 width="720" ALIGN=CENTER id=TEXT1>
            <tr>
              <td width="30%">Ваше имя:</td>
              <td>
                <input type="text" size="55" maxlength="80" name="name">    
                Пол:
                <INPUT TYPE="radio" NAME="gender" VALUE="male" CHECKED> Муж
                <INPUT TYPE="radio" NAME="gender" VALUE="female"> Жен
              </td>
            </tr>
            <tr>
              <td width="30%">Ваш E-mail:</td>
              <td><input type="text" size="80" maxlength="80" name="email"></td>
            </tr>
            <tr>
              <td width="30%">Ваш Web-адрес:</td>
              <td><input type="text" size="80" maxlength="80" name="web"></td>
            </tr>
            <tr>
              <td width="30%">Текст записи:</td>
              <td><textarea name="mess" rows="10" cols="69" wrap="VIRTUAL"></textarea></td>
            </tr>
          </table>
          <DIV ALIGN="center"><BR>
            <INPUT TYPE="SUBMIT" VALUE="Добавить">    
            <INPUT TYPE="RESET" VALUE="Очистить">
          </DIV>
        </form>
        </TD>
      </TR>
    </TABLE>
    </BODY>
    </HTML>
    
    Выглядит он следующим образом:

             Добро пожаловать в нашу гостевую книгу.   На этой странице Вы можете добавить свой отзыв о нашем сайте в книгу, а нажав сюда, Вы cможете просмотреть другие отзывы, оставленные ранее.


    Ваше имя:     Пол: Муж Жен
    Ваш E-mail:
    Ваш Web-адрес:
    Текст записи:

       

    Файл guestview.html

    <HTML>
    <HEAD>
    <META http-equiv="Content-Type" content="text/html; charset=windows-1251">
    <TITLE>Гостевая книга : Просмотр записей</TITLE>
    </HEAD>
    <BODY BGCOLOR="#C5BC9B" TEXT="#000000" LINK="#0000FF" VLINK="#800080" ALINK="#FF0000">
    <TABLE WIDTH=780 HEIGHT=150 BORDER=1 ALIGN="CENTER" CELLPADDING=10 CELLSPACING=0 BGCOLOR="#F6E9C0">
      <TR VALIGN="TOP">
        <TD>
        Добро пожаловать в нашу гостевую книгу.   На этой странице Вы можете просмотреть
        отзывы, которые были оставленны ранее, а нажав <A HREF="guestadd.html">сюда</A>,
        Вы cможете добавить свой отзыв о нашем сайте в книгу.
        <P><BR>
        <FORM ACTION="/cgi-bin/guest.cgi" NAME="RecordForm" METHOD="POST" TARGET="_top">
          <INPUT TYPE="HIDDEN" NAME="record" VALUE="view">
          <table border=0 width="410" ALIGN=CENTER id=TEXT>
            <tr>
              <td>Количество записей на странице:  
                <SELECT NAME="recinpage">
                  <OPTION VALUE="1"> 1
                  <OPTION VALUE="5"> 5
                  <OPTION VALUE="10"> 10
                  <OPTION VALUE="20"> 20
                  <OPTION VALUE="50"> 50
                </SELECT>  
                <INPUT TYPE="SUBMIT" VALUE="Смотреть">
              </td>
            </tr>
          </table>
        </form>
        </TD>
      </TR>
    </TABLE>
    </BODY>
    </HTML>
    
    Выглядит он следующим образом:

              Добро пожаловать в нашу гостевую книгу.   На этой странице Вы можете просмотреть отзывы, которые были оставленны ранее, а нажав сюда, Вы cможете добавить свой отзыв о нашем сайте в книгу.


    Количество записей на странице:    

    Как понятно из вышеприведенных текстов для добавления записи требуется ввести имя, пол, E-mail адрес, Web адрес и свой комментарий.   Для просмотра записей нужно указать какое количество записей на странице Вы хотите видеть.

    А теперь приступим к созданию скрипта.

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

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

            if ($FORM{'record'} eq "add")         # добавление записи
              {
              }
            elsif ($FORM{'record'} eq "view")     # просмотр записей
              {
              }
           exit 0;
    
    Для начала пройдемся по ветви добавления записи.

    Первое, что нужно сделать - это сформировать новую запись.   Запись строится сразу в HTML-виде, без разделения на поля.   Для этого мы выделяем цветом имя оставившего запись.   Затем проверяем заданы ли E-mail и Web адреса и если заданы, то оформляем их в виде ссылок.   После этого добавим дату и время записи.   Пол нам нужен для того, чтобы указать "написал" или "написала" новое сообщение.   И, наконец, добавим само сообщение.

    После того, как запись сформирована, ее нужно сохранить в файле.   Для этого используется следующий фрагмент кода:

        if (!open(DATAF, "<$GUESTFILE"))
               {  $mess="Невозможно открыть файл с записями.<br>
                         Вероятно произошла ошибка на сервере.";
                  &Error($mess);
               }
             else
               {  @records=<DATAF>;
                  close DATAF;
                  unshift @records, $newrecord;
                  if (!open(DATAF, ">$GUESTFILE"))
                    {  $mess="Невозможно открыть файл с записями.<br>
                              Вероятно произошла ошибка на сервере.";
                       &Error($mess);
                    }
                  else
                    {  flock DATAF, 2;
                       print DATAF @records;
                       flock DATAF, 8;
                       close DATAF;
                    }
               }
    
    Здесь мы сперва читаем файл с записями, затем вставляем новую запись на первое место в файле (оператором unshift) и после этого сохраняем файл.   В системе Windows нужно закомментировать строки flock DATAF, 2; и flock DATAF, 8;, так как эта функция пока не реализована в Perl for Windows.   Для блокировки файла можно использовать пример, описанный в шестом выпуске рассылки.

    Теперь, после того, как запись добавлена, остается только уведомить пользователя об этом:

         &PrintHtml("Запись добавлена", "Ваша запись была успешно добавлена.  Спасибо за ваш отзыв.");
    
    Теперь перейдем к ветви просмотра записей.

    Если количество записей в базе меньше запрошенного на одной странице, то вернем в браузер пользователя сразу все записи:

        if (($FORM{'recinpage'}>=@records) && ($FORM{'contfrom'}==undef))
          {  &Printtpl("head");
             print @records;
             &Printtpl("foot");
             exit 0;
          }
    
    Если количество записей в базе больше запрошенного на одной странице, то будем возвращать пользователю требуемое количество записей, при этом учитывая количество уже просмотренных записей:
        if ($FORM{'contfrom'}!=undef)
          {  @return=splice(@records, $FORM{'contfrom'}, $FORM{'recinpage'});
          }
        else
          {  @return=splice(@records, 0, $FORM{'recinpage'});
          }
    
    И, наконец, нам нужно сформировать ссылки продолжения просмотра и возврата к предыдущим записям:
        if ($FORM{'contfrom'}!=undef)
          {  $startfrom=$FORM{'contfrom'}-$FORM{'recinpage'};
    print "<A HREF=\"/cgi-bin/guest.cgi?record=view&recinpage=$FORM{'recinpage'}&contfrom=$startfrom\">Предыдущие $FORM{'recinpage'}</A>\n";
          }
        if ($FORM{'contfrom'}+$FORM{'recinpage'}<$record)
          {  $startfrom=$FORM{'contfrom'}+$FORM{'recinpage'};
    print "<A HREF=\"/cgi-bin/guest.cgi?record=view&recinpage=$FORM{'recinpage'}&contfrom=$startfrom\">Следующие $FORM{'recinpage'}</A>\n";
          }
    
    Кажется все.   А теперь полный текст скрипта guest.cgi
    #!/usr/bin/perl
    
    %FORM=();
    $mess='';
    $newrecord='';
    $GUESTFILE='./data/guest/guestbook.dat';
    
    ($result, $mess)=&GetFormInput;   # произвели разбор запроса
    &Error($mess) if ($result==0);    # если неудачно - сообщение
    
    if ($FORM{'record'} eq "add")
      {  $FORM{'mess'}=~s/^(\S+)/ \  \  \  $1/g;
         $FORM{'mess'}=~s/\n/<BR> \  \  \  /g;
         $FORM{'mess'}=~s/\r//g;
         @datatime=localtime(time);
         $Time=$datatime[2].":".(length($datatime[1])==1 ? "0".$datatime[1] : $datatime[1]);
         $Data=(length($datatime[3])==1 ? "0".$datatime[3] : $datatime[3]).".".
               (length($datatime[4])==1 ? "0".$datatime[4] : $datatime[4]).".".
               ($datatime[5]+1900);
         $newrecord="<HR><P><FONT COLOR=\"#AD1D09\">$FORM{'name'}</FONT>";
         if ($FORM{'email'} ne "")
           {  $newrecord.="  (E-mail: <A HREF=\"mailto:$FORM{'email'}\">$FORM{'email'}</A>";
              if ($FORM{'web'} ne "")
                {  $newrecord.=", Web: <A HREF=\"$FORM{'web'}\">$FORM{'web'}</A>),  ";
                }
              else
                {  $newrecord.="),  ";
                }
           }
         elsif ($FORM{'web'} ne "")
           {  $newrecord.="  (Web: <A HREF=\"$FORM{'web'}\" TARGET=\"_blank\">$FORM{'web'}</A>),  ";
           }
         else
           {  $newrecord.=",  ";
           }
         $newrecord.="побывав у нас в гостях, $Data в $Time";
         if ($FORM{'gender'} eq "male")
           {  $newrecord.=" написал следующее:<P>";
           }
         else
           {  $newrecord.=" написала следующее:<P>";
           }
         $newrecord.="$FORM{'mess'}<P>\n";
         if (!open(DATAF, "<$GUESTFILE"))
           {  $mess="Невозможно открыть файл с записями.<br>Вероятно произошла ошибка на сервере.";
              &Error($mess);
           }
         else
           {  @records=<DATAF>;
              close DATAF;
              unshift @records, $newrecord;
              if (!open(DATAF, ">$GUESTFILE"))
                {  $mess="Невозможно открыть файл с записями.<br>Вероятно произошла ошибка на сервере.";
                   &Error($mess);
                }
              else
                {  flock DATAF, 2;
                   print DATAF @records;
                   flock DATAF, 8;
                   close DATAF;
                }
           }
             # Сгенерируем ответ
         &PrintHtml("Запись добавлена", "Ваша запись была успешно добавлена.   Спасибо за отзыв о нашей работе.");
      }
    elsif ($FORM{'record'} eq "view")
      {  if (!open(DATAF, "<$GUESTFILE"))
           {  $mess="Невозможно открыть файл с записями.<br>Вероятно произошла ошибка на сервере.";
              &Error($mess);
           }
         else
           {  @records=<DATAF>;
              $record=@records;
              close DATAF;
              if (($FORM{'recinpage'}>=@records) && ($FORM{'contfrom'}==undef))
                {  &Printtpl("head");
                   print @records;
                   &Printtpl("foot");
                   exit 0;
                }
              if ($FORM{'contfrom'}!=undef)
                {  @return=splice(@records, $FORM{'contfrom'}, $FORM{'recinpage'});
                }
              else
                {  @return=splice(@records, 0, $FORM{'recinpage'});
                }
              &Printtpl("head");
              print @return;
              print "<CENTER>\n";
              if ($FORM{'contfrom'}!=undef)
                {  $startfrom=$FORM{'contfrom'}-$FORM{'recinpage'};
                   print "<A HREF=\"/cgi-bin/guest.cgi?record=view&recinpage=$FORM{'recinpage'}&contfrom=$startfrom\">Предыдущие $FORM{'recinpage'}</A>\n";
                }
              if ($FORM{'contfrom'}+$FORM{'recinpage'}<$record)
                {  $startfrom=$FORM{'contfrom'}+$FORM{'recinpage'};
                   print "<A HREF=\"/cgi-bin/guest.cgi?record=view&recinpage=$FORM{'recinpage'}&contfrom=$startfrom\">Следующие $FORM{'recinpage'}</A>\n";
                }
              print "</CENTER>\n";
              &Printtpl("foot");
           }
      }
    exit 0;
    
             # Подпрограммы
    
    sub Printtpl
    {  local($hf)=$_[0];
    
       if ($hf=~/head/)
         {  print <<END_HTML;
    Content-Type: text/html
    
    <HTML>
    <HEAD>
    <META http-equiv="Content-Type" content="text/html; charset=windows-1251">
    <TITLE>Гостевая книга : Просмотр записей</TITLE>
    </HEAD>
    <BODY BGCOLOR="#C5BC9B" TEXT="#000000" LINK="#0000FF" VLINK="#800080" ALINK="#FF0000">
    <TABLE WIDTH=780 HEIGHT=100% BORDER=1 ALIGN="CENTER" CELLPADDING=10 CELLSPACING=0 BGCOLOR="#F6E9C0">
    <TR VALIGN="TOP">
    <TD>
    END_HTML
         }
       if ($hf=~/foot/)
         {  print <<END_HTML;
    </TD>
    </TR>
    </TABLE>
    </BODY>
    </HTML>
    END_HTML
         }
    }
    
        # Подпрограмма вывода сообщения об ошибке
    sub Error
    {  local($message)=$_[0];
    
       &PrintHtml("Произошла ошибка", $message);
       exit 0;
    }
    
        # Подпрограмма вывода HTML-документа
    sub PrintHtml
    {  local($title, $message)=@_;
    
       print <<END_HTML;
    Content-Type: text/html
    
    <HTML>
    <HEAD>
    <META http-equiv="Content-Type" content="text/html; charset=windows-1251">
    <TITLE>$title</TITLE>
    </HEAD>
    <BODY>
    $message
    </BODY>
    </HTML>
    END_HTML
    }
    
        # Подпрограмма разбора входного запроса
    sub GetFormInput
    {  local($name, $value, $buffer, $err, $pair, @pairs);
    
       $err="";
       if ($ENV{'REQUEST_METHOD'} eq 'GET')
         {  @pairs=split(/&/, $ENV{'QUERY_STRING'});
         }
       elsif ($ENV{'REQUEST_METHOD'} eq 'POST')
         {  read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
            @pairs=split(/&/, $buffer);
         }
       else
         {  $err="Возможно произошла внутренняя ошибка сервера.<br>";
            $err.="Попытайтесь повторить отправку данных.";
            return(0, $err);
         }
       foreach $pair (@pairs)
         {  ($name, $value)=split(/=/, $pair);
            $value=~tr/+/ /;
            $value=~s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/gem;
            $FORM{$name}=$value;
         }
       return(1, $err);
    }
    





    "Лучшая ссылка"


    Сегодня в этом разделе я хочу дать ссылку, которая имеет к Perl'у весьма отдаленное, да и к тому же косвенное отношение.

    Недавно, проходя мимо книжного киоска, я заметил в нем книгу, которая меня весьма сильно заинтересовала.   Купив ее, я понял, что не ошибся. Она называется "Perl: Специальный справочник" и выпущена издательством "Питер" (http://www.piter-press.ru).

    Книга совсем новая, она была издана в сентябре 2000 года и представляет собой перевод книги Стивена Холзнера, выпущенной издательством "Coriolis" в 1999 году.

    Если Вы сталкивались уже с "Питерскими" книгами серии "Справочник", то мне Вам и объяснять ничего не придется, а если нет, то могу сказать что более ценного справочника по языку, его синтаксису, применению и возникающим проблемам мне на сегодняшний день не попадалось, хотя в моей библиотеке есть теперь 5 книг по Perl'у, не считая электронной литературы.

    Эта книга, при ее заказе непосредственно на сайте издательства "Питер" (http://www.piter-press.ru) стоит 95 рублей.   Ее объем - около 500 страниц, причем 500 страниц качественной информации.

    На этом же сайте Вы можете заказать и многие другие книги по разным направлениям, причем по ценам издательства.   Здесь же можно и посмотреть прайс-лист на печатную продукцию издательства.   Кроме того, Вы можете написать их письмо с просьбой выслать этот каталог по электронной почте.   Писать можно по следующим адресам: book@piter-press.ru и sales@piter-press.ru.

    Надеюсь, что эта книга поможет Вам в изучении этого прекрасного языка.




    О рассылке


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

    Домашняя страница этой рассылки в Каталоге subscribe.ru: http://subscribe.ru/catalog/comp.soft.prog.perlprog/, здесь же Вы можете и подписаться на данную рассылку.

    Архив этой рассылки находится на subscribe.ru по адресу: http://subscribe.ru/archive/comp.soft.prog.perlprog/

    Данная рассылка распространяется только через subscribe.ru.

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




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


    Виталий Ярошевский vitalij@newmail.ru


    При подготовке данной рассылки были использованы следующие материалы:

    1. "Изучаем Perl.   Глава 5"     Андрей Сергиенко



    http://subscribe.ru/
    E-mail: ask@subscribe.ru
    Поиск

    В избранное