Создание серверных приложений на языке PERL

         

Прекрасный язык Perl


Вы наверное обратили свое внимание что CGI скрипты пишутся обычно на языке Perl (Practical Extraction and Report Language)- очень удобном языке,впитавшем из других все лучшие черты.Может у вас возникнуть сомнение :Ну вот!Изучать новый язык программирования!? Спешу вас успокоить,изучение Perl не будет в тягость (я сужу по своему опыту!). Вы даже сами не заметите как выучите его.Если вы хоть когда-нибудь программировали скажем на C и использовали утилиту grep для поиска регулярных выражений в тексте,то вам будет еще легче.Мое изучение Perl

началось с того что я скачал Perl

под Windows (фирмы ActiveWare) и изучения той HTMLой документации которая к нему прилагалась хватило чтоб этот язык стал моим любимым....

Все в нем сделано для удобства программиста (в отличии например от Java;( )

Начнем с переменных,они в Perl

бывают 3х типов скаларные,списковые(массивы)

и хэши(ассоциативные массивы). Для указания компилятору(да и для немалого удобства программиста) перед именем скалярной переменной стоит знак '$' перед массивом '@',перед хешем '%'. т.е. например $scalar_var,@array_var,%hash_var

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

Например: "123"+"4" будет 127 (или "127") так как операция '+' действует над числами а вот если применить операцию конкатенации строк '.'

то строковое "test" . 1 будет "test1"

Ну а вот операции над скалярными переменными:



Операцыи Описание Пример
+ - * / % Арифметические print 2*7+4/(8%3);

print int(127/15); #целая часть

** Возведение в степень print 2**16;
++ -- Инкремент-декремент $i++;
& | ^ ~ << >> Побитовые $x=3;$y=4;

print $x|$y;

print $x&$y;

== != < > <= >= <=> Числовые операции сравнения if($x==9){print "Ok!";}
eq ne lt gt le ge cmp стрковые операции сравнения if($game eq 'doom'){print "You are doomer!\n";}
|| && ! Логические if(($x==9)||($game eq 'doom')){print "hello you!\n";}
?: Условный оператор $x=($game eq 'quake'?9:8);
, Последовательное вычисление $x=10,$y=20;
. Конкатенация $x='http://'.'www.uic.nnov.ru';
x Повторение $x='1234'x5; #$x='12341234123412341234'
=~ Сопоставление с образцом if($url=~/http/){print "HTTP";}
!~ То же но с отрицанием if($url!~/http/){print "No HTTP";}
= += -= *= /= %= **= |= &= ^= ~= <<= >>= .= x= Присваивание $x+=$y;
   
<
Пусь это будет вам справочником ,да кстати насчет строк,вы заметили,что они могут быть в двойных и одинарных кавычках, разница между ними состоит в том ,что в одинарных не осуществляется подстановка переменных, а в двойных осущестляется, Например:



$x='qwerty'; print 'my var is $x'; #выведет my var is $x print "my var is $x"; #выведет my var is qwerty


Списки: Спискочные переменные начинаются с символа '@'

конструируются следующим образом



@List1=(1,2,5,70); @List2=(12,23,@List1); #12,23,1,2,5,70 @Rgb=($r,$g,$b);


Также можно список использовать как lvalue:



@List=(1,2,3..8,15); ($x,$y,$z)=@List; #$x=1,$y=2,$z=3 ($x,$y,$z,@list2)=@List; #$x=1,$y=2,$z=3,@list2=(4,5,6,7,8,15); ($r,$g,$b)=@Rgb;


Можно обращаться к нескольким,выбраным элементам массива(срезу массива):



@list=(1..10); @list[2,3,5,9]=(100,200,300,400); #@list=(1,100,200,4,300,6,7,8,400,10) @list[1,10]=@list[10,1];#меняет местами элементы


Обратится к скаларному значению -элементу массива можно $имя_массива[индекс], сдесь обратите внимание на знак '$'- мы ведь обращаемся к скаляру-элементу.

Теперь немного о хешах:

хеш это такой массив который состоит из пар ключ-значение, весь хеш обозначается %хеш ,к отдельным элементам доступ $хеш{скалярное выражение} конструируется хеш так:



$my_hash{1}="doom"; $my_hash{'quake'}="www.idsoftware.com"; $my_hash{1+2}=100;


Хеш может быть также сконструирован из массива с четным числом элементов где пары превращаются в ключ-значение



%hash=(1,20,2,100);#аналогично $hash{1}=20;$hash{2}=100;


удаление из хеша -операция delete:



delete $hash{1};


есть функции выдающие ключи и значения соответственно.



%hash=(1,20,2,100,3,'doom'); @k=keys %hash; #@k=(1,2,3); @v=values %hash;#@v=(20,100,'doom');


Операторы:

Набор операторов в Perl Очень широк,многие из них прямые аналоги имеющихся в других языках,например if,for,while;но есть и значительные улучшения имеюшихся и конечно новые...

Тот же самый оператор if имеет две формы (как когда удобнее):





if(условие)оператор; оператор if условие;


В пару к оператору if имеется оператор unless : означающий if

с отрицанием:



unless(($method eq 'GET')||($method eq 'POST')){print "Unsupported method";} print "Ok" unless $x < $y;


Также в пару while существует until

синтаксис оператора for

полностью аналогичен C:



for($i=0;$i


новшеством(и приятным) является foreach позволяющий пройтись по всем элементам массива,присваивая по очереди его элементы какой-то переменной, его синтаксис такой:



foreach $переменная (@массив){ блок операторов; } или foreach (@массив){ операторы; }


Последний пример особенно важен для упрощения вашего тяжкого труда програмиста и демонтстрирует интересную особенность Perl-переменную по умолчанию $_: в оргомном количестве операторов и функций при опускании аргумента она подразумевается по умолчанию. Она также по умолчанию сопоставляется с регулярным выражением:



следующий пример @Data=<STDIN>; foreach(@Data){ chomp; print if /^From:/; } аналогичен такому: @Data=<STDIN>; foreach $_ (@Data){ chomp($_); print $_ if $_ =~ /^From:/;


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

регулярное выражение записывается между двух слэшей /рег_выр/



if(/abc/){ print '$_ содержит abc\n'; }


это самый простой пример применения регулярного выражения а теперь посложнее вот тут в табличке (из того что я помню наизусть):

Символ Значение Пример применения
. Соответствует любому символу print if /ab.c/;
[мн-во симв] Соответствует любому символу из данного мн-ва /[abc]d/;#соответствует ad,bd,cd
[^мн-во] Отрицание мн-ва символов /[^xyz]/;#
(....) Группировка элементов(и также запоминание в переменных $1 $2 $3 ...) /(xyz)*/

/([abc].[^xy]qwerty)/
(..|..|..) Одна из альтернатив  
* повторение образца 0 или более раз /.*/;#соответствует всему
? Повторение 0 или 1 раз /(http:\/\/)?.*\.cgi/
+ Повторение 1 или более раз  
{n,m} повторение от n до m раз  
{n} повторение точно n раз  
{n,} повторение n и более раз  
Спец символы:    
\t \r \n ... Управляющие символы:табуляции,возврат каретки,перевод строки.....  
\d Соответствует цифре,Аналог [0-9]  
\D Соответствует нецифровому симсволу,аналог[^0-9]  
\w Соответствует букве  
\W Соответствует небуквеному символу  
\s Соответствует пробельным символам(пробелы,табуляции,новые строки..)  
\S Соответствует непробельному символу  
\b Соответствует границе слова $test1="this is test";

$test2="wise";

if($test1=~/\bis\b/){print "1";}#соответствует

if($test2=~/\bis\b/){print "2";}#нет
\B Соответствует не границе слова /\Bis\B/ соответсвует 'wise' но не 'is'
<


Для того чтоб поместить в регулярное выражение любой специальный символ,поставьте реред ним обратный слэш Заставить Perl игнорировать регистр можно поставив i после регулярного выражения



print "Are you sure?:"; $answer=<STDIN>; if($answer=~/Y/i){ #че-нибудь сделаем... }


Полезные функции.

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

глобальная(по всей строке) замена -опция g; Пример:



$x="This is test"; $x=~s/ /_/g; print $x; #This_is_test


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



open OLD,"oldfile.txt" || die "Cannot open oldfile.txt $!\n"; open NEW,">newfile.txt" || die "Cannot open newfile.txt $!\n"; foreach(){ s/(\d+)(\s+год)/($1+1).$2/gie; s/(\d+)(\s+лет)/($1+1).$2/gie; print NEW $_; } close NEW; close OLD;


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



sub urldecode{ local($val)=@_; $val=~s/\+/ /g; $val=~s/%([0-9A-H]{2})/pack('C',hex($1))/ge; return $val; }


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

Операция Описание Пример использоввания
-r Доступен для чтения unless(-r "myfile"){print "Cannot read myfile\n";}
-w Доступен для записи  
-x Для исполнения  
-o Принадлежит пользователю if(-o "index.htm"){chmod 0777,"index.htm";}
-R Доступен для чтения реальным

пользователем,а не только "эффективным".

Имеет значения для set-uid -скриптов
if(-r FILE){unless(-R FILE){die "Its not allowed to read this\n";}}
-W Доступен для записи реальным пользователем  
-X Доступен для исполнения реальным пользователем  
-O Принадлежит реальному пользователю  
-e Файл или каталог Существует unless(-e $htmlfile){

open HTML,">$htmlfile";

print HTMLFILE "<HTML><BODY></BODY></HTML>";

close HTMLFILE;

}
-z Существует,но имеет нулевую длину if(-z 'tmpfile'){unlink 'tmpfile';}
-s Размер файла в байтах system "rar m -m5 archive.rar $myfile" if -s $myfile > 1000;
-f Файл существует и является простым файлом  
-d Файл существует и является каталогом if(-d 'public_html'){chdir 'public_html';}
-l Символической ссылкой  
-p Каналом FIFO  
-u Имеет бит установки пользователя  
-g Имеет бит установки группы  
-k Установлен sticky-бит  
-t Является терминальным устройством  
-M Время с последнего изменения (в днях) while(defiled($file=glob('*'))){

 if(-M $file >= 7.0){

  unlink($file);#удаляем слишком старые файлы

  }

}
-A Время последнего доступа(в днях) if(-A "$ENV{'HOME'}/public_html/index.html"
-C Время последнего обновления файлового индекса(в днях)  
     
<


Еще есть и другие

функция open открывает файл



open ФАЙЛОВАЯ_ПЕРЕМЕННАЯ,"имя файла"; # открыть файл для чтения open ФАЙЛОВАЯ_ПЕРЕМЕННАЯ,">имя файла"; #для записи open ФАЙЛОВАЯ_ПЕРЕМЕННАЯ,">>имя файла";#для записи в конец open ФАЙЛОВАЯ_ПЕРЕМЕННАЯ,"+


Что какается открытия файлов,то вам как програмистам все очевидно, но с коммандами тоже все здорово,что пояснит хороший пример(из практики):



open MAIL,"|mail paaa@uic.nnov.ru";#Пошлем информацию по почте print MAIL "Hello\n"; print MAIL "...\n"; print MAIL "...\n"; close MAIL;


когда вы открыли файл вы можете считать из него строку в скалярную переменную Вот так:$str=<FILE>

избавиться от символа новой строки на конце поможет функция chomp, ведь этот символ может помешаться например в имени файла или при выводе на экран



print "Введите имя файла:"; $fname=<STDIN>; chomp($fname); open F,$fname || die "Cannot open $fname $!\n"; .....


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



print "Что искать:"; $search=<STDIN>; chomp($search); @L=<F>; foreach(@L){ print if /$search/; } а можно и так: print "Что искать:"; $search=<STDIN>; chomp($search); foreach(<F>){ print if /$search/; }


бинарный файл можно читать и писать функциями sysread и syswrite:

sysread ФАЙЛОВАЯ_ПЕРЕМЕННАЯ,$скалярная_перемменая,сколько_байт

syswrite ФАЙЛОВАЯ_ПЕРЕМЕННАЯ,$скалярная_перемменая,сколько_байт

функции split и join: @Список=split /рег.выр/,$скаляр;

$скаляр=join строка,@Список;



#Разбить строку слов,разделенных пробелами в список вы можете @WordList=split / /,$String; #После обработки снова обьединить $String=join ' ',@WordList;


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



printf "x=%d",$x; printf ("x=%d",$x);#аналогично




Надеюсь что я вас позабавил примерами функций ;).

Примеры применения Perl для различных нужд...

Следующая программа переводит текстовый файл в формат HTML (вспомните сколько хлопот вам доставит отлов во всем файле '<', '>' и '&' чтоб заменить их на &tl; , &gt; и &amp;

а как неплохо чтоб автоматически все http://www.... превратились в <A href="http://www...." >http://www....</A>)



#!/usr/bin/perl #txt2html die "Usage: txt2html Infile OutFile\n" unless(@ARGV); open IN,"$ARGV[0]" || die "Cannot open $ARGV[0] $! \n"; open OUT,">$ARGV[1]" || die "Cannot open $ARGV[1] $! \n"; while(<IN>){ s/&/&amp;/g; s/</&lt;/g; s/>/&gt;/g; s/\n/<BR>\n/g; s/(http:\/\/\S+)/<A href="$1">$1<\/A>/g; print OUT $_; } close IN; close OUT;


Более подробную информацию о Perl вы можете получить по адресам:

http://www.perl.com

http://www.metronet.com/0/perlinfo/perl5/manual/perl.html

http://www.ActiveWare.com/


Содержание раздела