Прекрасный язык 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; , > и
&
а как неплохо чтоб автоматически все
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/&/&/g; s/</</g; s/>/>/g; s/\n/<BR>\n/g; s/(http:\/\/\S+)/<A href="$1">$1<\/A>/g; print OUT $_; } close IN; close OUT;
Более подробную информацию о
Perl вы можете получить по адресам:
http://www.metronet.com/0/perlinfo/perl5/manual/perl.html