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

         

Дескрипторы файлов и проверка файлов.


Открытие и закрытие дескрипторов файлов.

Функция die.

Использование дескрипторов файлов.

Операции для проверки файлов.

Функции stat и lstat.



Дизьюнкция.


a|b|c - означает, что данный образец соответствует только одному из указанных вариантов. Такая конструкция работает и для класса символов, как в образце /igor|mike/.



Доступ к каталогам.


Доступ к каталогам.

Развертывание.

Открытие и закрытие дескриптора каталога.

Чтение дескриптора каталога.


Пример:

chdir("/etc") || die "cannot cd to /etc ($!)";

print "where do you want to go? "; chomp($where = <STDIN&gt); if(chdir $where) { # OK } else { # NOT }





Другие компоненты формы.


Пример:

#/usr/bin/perl5 -w

use strict; use CGI qw(:standard);

print header; print start_html("Ice Cream Stand"), h1("Ice Cream Stand"); if(param()) { my $who = param("name"); my $flavor = param("flavor"); my $scoops = param("scoops"); my $taxrate = 1.0743; my $cost = sprintf("%.2f", $taxrate * (1.00 + $scoops*0.25)); print p("Ok, $who, have $scoops scoops of $flavor for\$$cost."); } else { print hr(); print start_form(); print p("What is your name? ", textfield("name")); print p("What flavor: ", popup_menu("flavor", ['mint', 'cherry', 'mocha'])); print p("How many scoops? ", popup_menu("scoops", [1..3])); print p(submit("order"), reset("clear")); print end_form(), hr(); } print end_html();



Другие вызывающие последовательности.


Прокручиваемый список:

print scrolling_list( -NAME =&gt "flavors", -VALUES =&gt [qw(mint chocolate cherry vanilla peach)], -LABELS =&gt { mint =&gt "Mightly Mint", chocolate =&gt "Cherished Chocolate", cherry =&gt "Cherry Cherry", vanilla =&gt "Very Vanilla", peach =&gt "Perfectly Peach", }, -SIZE =&gt 3, -MULTIPLE =&gt 1 # 1 - true, 0 - false );

-NAME - имя компонента формы,

-LABELS - ссылка на анонимный хеш,

-VALUES - ссылка на анонимный массивa ключей хеша,

-SIZE - сколько элементов списка видно одновременно,

-MULTIPLE - если 1 - можно выбирать более одного элемента списка.

Если -MULTIPLE в положении истина, можно делать:

@choices = param("flavors");

Еще один способ:

%flavors = ( "mint", "Mightly Mint", "chocolate", "Cherished Chocolate", "cherry", "Cherry Cherry", "vanilla", "Very Vanilla", "peach", "Perfectly Peach", ); print scrolling_list( -NAME =&gt "flavors", -LABELS =&gt \%flavors, -VALUES =&gt [keys %flavors], -SIZE =&gt 3, -MULTIPLE =&gt 1 # 1 - true, 0 - false );



Фиксирование образцов.


Некоторые особые виды записи позволяют фиксировать образец относительно позиции в строке, в кот. ищется соответствие.

Фиксирующая деректива \b требует, чтобы совпадение с образцом b происходило только на границе слова.

/fred\b/; # соответствует слову fred, но не Frederik /\bmo/; # соответствует словам moe и mole, но не Elmo /\bFred\b/; # соответствует слову Fred, но не Frederik или alFred /\b\+\b/; # соответствует "x+y", но не "++" или " + "

\B требует, чтобы в указанной точке границы слова не было. Символ ^ обозначает начало строки. Символ $ фиксирует образец по концу строки.

Поддерживаются и другие фиксирующие точки.



Функции.


Определение пользовательской функции.

Вызов пользовательской функции.

Возвращаемые значения.

Аргументы.

Локальные переменные в функциях.

Полулокальные переменные. Функция local.

.Создаваемые операцией my переменные файлового уровня.



Функции push и pop.


Использование массива в качестве стека.

push(@mylist, $newval); $oldval = pop(@mylist);

Работает и со списками:

@mylist = (1, 2, 3); push(@mylist, 4, 5, 6);



Функции split и join.


$line = "gds::*::1001::20::Samolyuk German::/home/gds::/usr/local/bin/tcsh"; @fields = split(/:/, $line); # разбить $line, используя в качестве # разделителя двоеточие # @fields содержит ("gds","","*","","1001","","20","","Samolyuk German","", # "/home/gds","","/usr/local/bin/tcsh")

Второе поле : стало пустой строкой, если вы этого не хотите:

@fields = split(/:+/, $line);

Использование автоматической переменной:

$_ = "this is a some text"; @words = split(/ /); # @words = split(/ /, $_);

Соседние пробелы вызовут появление пустых строк. Лучше использовать образец / +/

или /\s+/. Или по умолчанию:

@words = split; # @words = split(/\s+/, $_);

Пример:

$line = "gds::*::1001::20::Samolyuk German::/home/gds::/usr/local/bin/tcsh"; ($name, $password, $uid, $gid, $gcos, $home, $shell, $a) = split(/:+/, $line); # $a - undef

Функция join берет список значений с склеивает их, ставя между элементами списка строку связку:

$string = join($glue, @list); $outline = join(":", @fields);



Функции stat и lstat.


($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $mtime, $ctime, $blksize, $bloks) = stat(...);

($uid, &gid) = (stat("/etc/passwd"))[4, 5];



Функция chomp.


@stuff = ("hello\n", "world\n", "happy days") chomp(@stuff);



Функция delete.


Для удаления элементов хеша используется функция delete.

%test = ("abc", "cba", "12.7", "24.7"); delete $test{"abc"};



Функция die.


Функция die получает список, выводит этот список на STDERR, а затем завершает PERL-процесс с ненулевым кодом выхода.

open(DATA, ">/tmp/data") || die "Sorry, I couldn't open /tmp/data\n";

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

die "good bye";

die "good bye\n";

Использование переменной $!, содержащей строку последней из ошибок операционной системы.

open(LOG, ">>logfile") || die "cannot append:$!";

возможное сообщение: cannot append: Permission denied



Функция each.


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

while(($first, $last) = each(%test)) { print "The value of $first is $last"; }



Функция keys.


Функция keys(%hash_name) выдает список всех текущих ключей в хеше %hash_name. Если элементы в хеше отсутствуют, функция keys

возвращает пустой список.

Пример:

$test{"abc"} = "cba"; $test{12.7} = 21.7; @list = keys(%test); # @list = ("abc", 12.7) или (12.4, "abc")

Как и в остальных встроенных функциях круглые скобки не обязательны.

foreach $key (keys %test) { print "at $key we have $test{$key}\n"; }

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

В скалярном контексте функция keys выдает число элементов хеша.

if(keys( %hash)) { ... } # # or # while(keys(%hash) < 10) { ... }

Если обратится к переменной %hash в скалярном контексте, то будет возвращено значение ложь или истина (пустой или нет):

if(%hash) { # если истина ... ... }



Функция reverse.


@a = ( 7, 8, 9); @b = reverse(@a); # список-аргумент не меняется @b = reverse(@b);



Функция sort.


Возвращает отсортированный список не меняя оригинала.

@x = sort("small", "medium", "large");



Функция values.


Функция values(%hash_name) возвращает список всех текущих значений хеша в том же порядке, в каком функция keys возвращает ключи.

%test = (); # empty $test{"abc"} = "cba"; $test{"def"} = "fed"; @test_values = values(%test); # ("cba", "fed") или ("fed", "cba")



Генерирование формы.


HTML-страница, содержащая заполняемую форму:

<HTLM> <HEAD> <TITLE&gt Hello Ice Cream </TITLE> </HEAD> <BODY> <H1>Hello Ice Cream!</H1> <FORM ACTION="http://serv.edu.kiae.ru/~stsss/cgi-bin/ice_cream.cgi" METHOD="GET"&gt What is your flavor?<INPUT NAME="favorite" TYPE="text" VALUE="mint"> <P> <INPUT TYPE="submit"> </FORM> </BODY> </HTLM&gt

Вариант с использованием одного CGI-файла:

#!/usr/bin/perl5 -w

use CGI qw(:standard); my $favorite = param("flavor"); print header(); print start_html("Hello Ice Cream!"), h1("Hello Ice Cream!"); if($favorite) { print p("Your favorite flavor is $favorite"); } else { print hr, start_form; print p("Pleace select a flavor: ", textfield("flavor", "mint")); print end_form, hr } print end_html();



Хеш-функции.


Некоторые функции, предназначенные для обработки хешей.



Хеш-переменные.


Имя хеш переменной состоит из знака процента и буквы или нескольких. Обращение к элементам хеша %test производится путем указания $test{$key}, где $key - любое скалярное выражение.

Создание новых элементов хеша путем присваивания значения:

$test{"abc"} = "cba"; $test{12.7} = 21.7;

Оращение к элементам хеша:

print $test{"abc"}; $test{12.7} += 3; # разультат 24.7

При обращении к несуществующему элементу хеша возвращается значение undef.



Игнорирование регистра.


Игнорирование регистра /образец/i.

print "any last request? "; if(<STDIN&gt =~ /^y/i) { ... }



Интерполяция скаляров в строках.


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

$a = "fred"; $b = "some text $a"; # "some text fred" $c = "no such variable $what"; # "no such variable" $x = '$fred'; $y = "hey $x"; # 'hey $fred' $fred = 'hi'; $barney = "a test of " . '$fred'; #'a test of $fred' $barney1 = "a test of \$fred"; #'a test of $fred'

Разделитель имени переменной - {}

$barney = "It is ${fred}day";



Использование дескрипторов файлов.


Чтение строк из файла:

open(EP, "/etc/passwd"); while(<EP&gt) { chomp; print "I saw $_ in the passwdord file!\n"; } close(EP);

Для записи:

print LOGFILE "Finish!\n"; print STDOUT "Finish!\n";

Копирование данных из файла в файл:

open(IN, $a) || die "cannot open $a for reading: $!"; open(OUT, ">$b") || die "cannot create $b: $!"; while(<IN&gt) { print OUT $_; } close(IN) || die "cannot close $a: $!"; close(OUT) || die "cannot close $b: $!";



Использование другого разделителя.


Для нахождения строки, которая содержит несколько символов (/), нужно перед каждым из них поставить обр. косую черту.

$path = <STDIN>; # прочитать путь if(path =~ /^\/usr\/etc/) { # начинается с /usr/etc... }

Можно заменить разделитель, если перед любым специальным символом поставить букву m.

/^\/usr\/etc/ m@^/usr/etc@ m#^/usr/etc#



Использование интерполяции переменных.


Перед тем как регулярное выражение расспатривается, в нем производится интерполяция переменных

$what = "bird"; $sentence = "Every good bird does fly."; if($sentence =~ /\b$what\b/) { print "The centence contains theword $what!\n"; }



Использование подпрограмм.


#!/usr/local/bin/perl -w %words = qw( fred camel bamey llama betty alpaca irina alpaca ); print "What is you name? "; $name = <STDIN&gt ; chomp ($name); if($name =~ /^german\b/i) { print "Hello, German! How good of you to be here!\n"; } else { print "Hello, $name! \n"; print "What is a secret word? "; $guess = <STDIN&gt ; chomp($guess); while(! good_word( $name, $guess )) { print "Wrong, try again. What is a secret word? "; $guess = <STDIN&gt ; chomp($guess); } }

sub good_word { my($somename, $someguess) = @_; $somename =~ s/\W.*//; $somename =~ tr/A-Z/a-z/; if($somename eq "german") { return 1; } elsif(($words{$somename} || "grouhno") eq $someguess) { return 1; } else { return 0; } }



Использование таблицы секретных слов - хеш.


#!/usr/local/bin/perl # did not use -w becouse "" %words = qw( #Perl 5.004 fred camel bamey llama betty alpaca irina alpaca ); print "What is you name? "; $name = <STDIN&gt ; chomp ($name); if($name eq "German") { print "Hello, German! How good of you to be here!\n"; } else { print "Hello, $name! \n"; $secretword = $words{$name}; if($secretword eq "") { $secretword = "grouhno"; } print "What is the secret word? "; $guess = <STDIN&gt ; chomp($guess); while($guess ne $secretword) { print "Wrong, try again. What is a secret word? "; $guess = <STDIN&gt ; chomp($guess); } }



Круглые скобки как способ запоминания.


При совпадении с образцом никаких изменений не происходит, просто совпавшая часть строки запоминается, и к ней можно впоследствии обращаться. Например, (a) продолжает соответствовать букве a, а ([a-z]) - любой строчной букве.

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

/mike(.)igor\1/

Соответствует строке, состоящей из слова mike, любого символа, слова igor и еще одного такого же символа. Единица обозначает первую заключенную в круглые скобки часть регулярного выражения. Если таких частей больше, чем одни, то вторая обозначается как \2 ...

/a(.)b(.)c\2\1/;

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

/a(.*)b\1c/;

- a, любое количество символов, b, ту же последовательность символов, и c.



Литеральное представление.


(1, 2, 3); ("fred", 4.5); ($a, 17); ($a+$b, 17); (); # пустой список

Оператор конструктора списка. Пример:

(1 .. 5); # (1, 2, 3, 4, 5); (1.2 .. 5.2); # (1.2, 2.2, 3.2, 4.2, 5.2); ($a .. $b); (1.3 .. 3.1); # (1.3, 2.3)

@a = ("fred", "betty"); @a = qw(fred betty);

Использование списочного литерала в функции

print("The answer is ", $a, "\n");



Литеральное представление хеша.


Фактически в Perl никакого литерального формата для хеша не предусмотрено, поэтому он просто представляется в виде списка:

@test_list = %test; # @test = qw(abc cba 12.7 24.7); %test1 = @test_list; # создать test1 как test %test1 = %test; # ускоренный метод %test2 = ("abc", "cba", "12.7", "24.7"); # создать %test2 как %test # из литеральных представлений

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

Используя операцию reverse, можно создать хеш, в котором ключи и значения поменяются местами:

%backwards = reverse %normal;

Если %normal имеет два идентичных значения, то в %backwards

они преватятся в один элемент.



Литералы с плавающей запятой.


Литерал - константа. Примеры:

1.25 7.25e45 -12e-24 -1.2E-23



Локальные переменные в функциях.


При помощи операции my можно создавать локальные переменные

sub add { my($sum); $sum = 0; foreach $_ (@_) { $sum += $_; }

return $sum; }

sub bigger_than_100 { # создает список всех элементов массива &gt 100 my(@result); foreach $_ (@_) { if($_ > 100) { push(@result, $_); } } return @result; }

sub bigger_than { # создает список всех элементов массива &gt 100 my($n, @values); ($n, @values) = @_;

my($result); foreach $_ (@values) { if($_ > $n) { push(@result, $_); } } return @result; } @new = bigger_than(100, @list); @this = bigger_than(5, 1, 5, 15, 30); # @this содержит (15, 30)

Использовали две локальные переменные - это удобнее, чем указывать $_[0]

и @_[1..$#_].

Список, создаваемый my, можно использовать в правой части выражения:

my($n, @values) = @_;

my($sum) = 0;



Массивы и списочные данные.


Список и массив.

Литеральное представление.

Переменные.

Операции над массивами и функции обработки массивов.

Интерполяция массивов.



Множители.


* - ни одного или более экземпляров стоящего непосредственно перед ней символа.

+ - один или более экземпляров стоящего непосредственно перед нем символа.

? - ни одного или один экземпляр стоящего непосредственно перед ним символа.

Например, регулярное выражение /fo+ba?r/ обозначает символ f, за которым следует один или более символов o, затем символ b, затем ни одного или один символ a

и символ r.

$_ = "mike xxxxxxxxxxxxx nick" s/x+/igor/;

В последнем примере все символы x будут заменемы на igor (описанные выше образцы характеризуются
&quot прожорливостью &quot). Простой способ избежать этого - применение общего множителя.

/x{5,10}/ - найти символ, стоящий перед скобками, повторяющийся от пяти до десяти раз.

/x{5,}/ - найти символ, стоящий перед скобками, повторяющийся от пяти раз.

/x{5}/ - найти символ, стоящий перед скобками, повторяющийся ровно пять раз.

/x{,5}/ - найти символ, стоящий перед скобками, пять раз или менее.

/a.{5}b/ - соответствует букве a, отделенной от буквы b любыми пятью символами.

Если в одном выражении используются два множителя, то правило &quot прожорливости&quot дополняется правилом "чем левее, тем прожорливее &quot. Например:

$_ = "a xxx c xxxxxxxx c xxx d"; /a.*c.*d/;

Первая комбинация &quot.*&quot соответствует всем символам до второй буквы c.

Можно заставить любой множитель перестать быть "прожорливым", поставив после него вопросительный знак:

$_ = "a xxx c xxxxxxxx c xxx d"; /a.*?c.*d/;

Теперь a.*?c соответствует манимальному числу символов между a и c, а не максимальному.



Модификаторы выражений.


Синтаксис:

выражение if управляющее_выражение;

# эквивалентно

if(управляющее_выражение) { выражение; }

Оператор читается справа налево.

Другие формы с модификаторами:

выражение1 unless выражение2; выражение1 while выражение2; выражение1 until выражение2;

Пример:

chomp($n = ); $i = 1; $i *= 2 until $i > $n;

Эти формы нельзя вкладывать одну в другую!



Несколько файлов секретных слов в текущем каталоге.


#!/usr/local/bin/perl -w init_words(); print "What is you name? "; $name = <STDIN&gt ; chomp ($name); if($name =~ /^german\b/i) { print "Hello, German! How good of you to be here!\n"; } else { print "Hello, $name! \n"; print "What is a secret word? "; $guess = <STDIN&gt ; chomp($guess); while(! good_word( $name, $guess )) { print "Wrong, try again. What is a secret word? "; $guess = <STDIN&gt ; chomp($guess); } }

sub good_word { my($somename, $someguess) = @_; $somename =~ s/\W.*//; $somename =~ tr/A-Z/a-z/; if($somename eq "german") { return 1; } elsif(($words{$somename} || "grouhno") eq $someguess) { return 1; } else { open MAIL, "|mail gera"; print MAIL "bad news: $somename guessed $someguess\n"; close MAIL; return 0; } }

sub init_words { while(defined($filename = glob("*.secret"))) { open(WORDLIST, $filename) || die "can't open wordlist: $!"; if(-M WORDLIST >= 7.0) { die "Sorry, the wordlist is older than seven days."; } while($name = <WORDLIST&gt) { chomp($name); $word = <WORDLIST&gt ; chomp($word); $words{$name} = $word; } close(WORDLIST) || die "could not open wordlist: $!"; } }



Несколько секретных слов.


#!/usr/local/bin/perl -w @words = qw(camel lama aplaca); # Perl 5.004 print "What is you name? "; $name = <STDIN&gt ; chomp($name); if($name eq "German") { print "Hello, German! Good of you to be here!\n"; } else { print "Hello, $name! \n"; print "What is the secret word? "; $guess = <STDIN&gt ; $i = 0; $correct = "maybe"; while($correct eq "maybe") { if($words[$i] eq "guess) { $correct = "yes"; } elsif($i &lt 2) { $i = $i + 1; } else { print "Wrong, try again. What is the secret word? "; $guess = <STDIN&gt ; chomp($guess); $i = 0; } } }



Обьектно-ориентированное программирование на PERL.


Пусть модуль CGI возвращает обьект $query

$he_said = $query->param("answer");

Имя класса - имя модуля без расширения .pm (обычно).

Конструктор, необходимый для создания обьекта:

$query = CGI->new(); # or $query = new() CGI;



Обьекты в модуле CGI.pm.


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

#!/usr/bin/perl5 -w

use 5.004; use strict; use CGI qw(:standard); use Fcntl qw(:flock);

sub bail { # функция ошибок my $error = "@_"; print h1("Unexpected Error"), p($error), end_html; die $error; }

my ( $CHATNAME, # имя файла гостевой книги $MAXSAVE, # какое количество хранить $TITLE, # название и заголовок страницы $cur, # все текущие записи $entry, # одна конкретная запись );

$TITLE = "Simple Guestbook"; $SHATNAME = "/usr/tmp/chatfile"; $MAXSAVE = 10;

print header, start_html($TITLE); h1($TITLE);

my(@entries);

$cur = CGI -&gt new(); # текущий запрос if($cur -&gt param("message")) { # мы получили сообщение $cur -&gt param("data", scalar localtime); # установить текущее время @entries = ($cur); # записать сообщение в массив }

# открыть файл для чтения и записи (с сохранением предыдущего содержимого) open(CHANDLE, "+&lt $CHATNAME") || bail("canot open $CHATNAME: $!");

# получить эксклюзивную блокировку на гостевую книгу # (LOCK_EX == exclusive lock) flock(CHANDLE, LOCK_EX) || bail("canot flock $CHATNAME: $!");

# занести в $MAXSAVE старые записи (первой - самую новую) while(!eof(CHANDLE) && @entries < $MAXSAVE) { $entry = CGI -&gt new(\*CHANDLE); # передать дескриптор файла по ссылке push @entries, $entry; } seek(CHANDLE, 0, 0) || bail("canot rewind $CHATNAME: $!"); foreach $entry (@entries) { $entry -&gt save(\*CHANDLE); } truncate(CHANDLE, tell(CHANDLE)) || bail("canot truncate $CHATNAME: $!"); close(CHANDLE) || bail("canot close $CHATNAME: $!");

print hr, start_form; print p("Name:", $cur -&gt textfield(-NAME =&gt "name")); print p("Message:", $cur -&gt textfield( -NAME =&gt "message", -OVERRIDE =&gt 1, # стирает предыдущее сообщение -SIZE =&gt 50 ) ); print p(submit("send"), reset("clear")); print end_form, hr;

print h2("Prior Messages"); foreach $entry (@entiries) { printf("%s [%s]: %s", $entry -&gt param("date"), $entry -&gt param("name"), $entry -&gt param("message")); print br(); } print end_html;



Обработка различных вариантов ввода.


#!/usr/local/bin/perl %words = qw( #Perl 5.004 fred camel bamey llama betty alpaca irina alpaca ); print "What is you name? "; $name = <STDIN&gt ; chomp ($name); $original_name = $name; $name =~ s/\W.*//; $name =~ tr/A-Z/a-z/; if($name eq "german") { print "Hello, German! How good of you to be here!\n"; } else { print "Hello, $original_name! \n"; $secretword = $words{$name}; if($secretword eq "") { $secretword = "grouhno"; } print "What is the secret word? "; $guess = <STDIN&gt ; chomp($guess); while($guess ne $secretword) { print "Wrong, try again. What is a secret word? "; $guess = <STDIN&gt ; chomp($guess); } }



Обращение к элементам массива.


Элементы массива нумеруются целыми числами.

@fred = (7, 8, 9) $b = $fred[1]; $fred[5] = 0; ($fred[0], $fred[1]) = ($fred[1], $fred[0]);

Срез - обращение к списку элементов массива.

@fred[0, 1]; @fred[0, 1] = fred[1, 0]; @fred[0, 1, 2] = fred[1, 1, 1]; @fred[1, 2] = (9, 10);

@who = ( qw(fred barney betty wilma))[2, 3];

При обращении к элементу за пределами массива - undef. Массивы автоматически расширяются.

@betty = (1, 2, 3); $betty[6] = "ho"; # (1, 2, 3, undef, undef, undef, "ho");

@fred = qw(fred wilma pebbles dino); print $fred[-1]; # "dino" print $#fred; # 3 print $fred[$#fred]; # "dino"



Образцы, обозначающие один символ.


Одиночный символ соответствует самому себе. Символ точка - любой одиночный символ, кроме символа новой строки (\n). Например, образцу /a./ соответствует любая двухбуквенная поседовательность, начинающаяся с a.

Класс символов сопоставления:

/[abcde] # строка, содержащая любую из первых пяти строчных букв /[aeiouAEIOU] # -//- из первых пяти гласных

Диапазоны символов:

[0123456789] [0-9] [0-9\-] [a-z0-9] [a-zA-Z0-9_]

Отрицание класса символов:

[^0-9] [^aeiouAEIOU] [^\^]

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

Конструкция

Эквивалентный класс

Конструкция с отрицанием

Эквивалентный класс с отрицанием

\d (цифра) [0-9] \D (нецифровые символы) [^0-9]
\w (обычный символ) [a-zA-Z0-9_] \W (специальный символ) [^a-zA-Z0-9_]
\s (пробельный символ) [ \r\t\n\f] \S (непробельный символ) [^ \r\t\n\f]

Пример:

[\da-fA-F] # одна шестнадцатеричная цифра



Окончательный вариант программ.


Приветствие:

#!/usr/local/bin/perl -w init_words(); print "What is you name? "; $name = <STDIN&gt ; chomp ($name); if($name =~ /^german\b/i) { print "Hello, German! How good of you to be here!\n"; } else { print "Hello, $name! \n"; print "What is a secret word? "; $guess = <STDIN&gt ; chomp($guess); while(! good_word( $name, $guess )) { print "Wrong, try again. What is a secret word? "; $guess = <STDIN&gt ; chomp($guess); } } dbmopen(%last_good, "lastdb", 0666) || die "can't dbmopen lastdb: $!"; $last_good{$name} = time; dbmclose(%last_good) || die "can't dbmclose lastdb: $!";

sub good_word { my($somename, $someguess) = @_; $somename =~ s/\W.*//; $somename =~ tr/A-Z/a-z/; if($somename eq "german") { return 1; } elsif(($words{$somename} || "grouhno") eq $someguess) { return 1; } else { open MAIL, "|mail gera"; print MAIL "bad news: $somename guessed $someguess\n"; close MAIL; return 0; } }

sub init_words { while(defined($filename = glob("*.secret"))) { open(WORDLIST, $filename) || die "can't open wordlist: $!"; if(-M WORDLIST >= 7.0) { rename($filename, "$filename.old") || die "can't rename $filename to $filename.old: $! "; } while($name = <WORDLIST&gt) { chomp($name); $word = <WORDLIST&gt ; chomp($word); $words{$name} = $word; } close(WORDLIST) || die "could not open wordlist: $!"; } }

Листер паролей:

#!/usr/local/bin/perl -w while(defined($filename = glob("*.secret"))) { open(WORDLIST, $filename) || die "can't open wordlist: $!"; if(-M WORDLIST >= 7.0) { die "Sorry, the wordlist is older than seven days."; } while($name = <WORDLIST&gt) { chomp($name); $word = <WORDLIST&gt ; chomp($word); write; } close(WORDLIST) || die "could not open wordlist: $!"; } format STDOUT = @&lt&lt&lt&lt&lt&lt&lt&lt&lt&lt&lt&lt&lt&lt @&lt&lt&lt&lt&lt&lt&lt&lt @&lt&lt&lt&lt&lt&lt $filename, $name, $word . format STDOUT_TOP = Page @&lt&lt $%

Filename Nname Word ================ ========= ======= .

Программа последнего правильного ввода пароля:

#!/usr/local/bin/perl -w dbmopen(%last_good, "lastdb", 0666) || die "can't dbmopen lastdb: $!"; foreach $name (sort keys (%last_good)) { $when = $last_good{$name}; $hours = (time() - $when) / 3600; write; }

format STDOUT = User @&lt&lt&lt&lt&lt&lt&lt&lt&lt&lt: last correct guess was @&lt&lt&lt hour ago. $name, $hours .



Операции для проверки файлов.


Опреация -e $fele проверяет факт существования файла. Возвращает значения истина или ложь.

$name = "index.html"; if(-e $name) { print "I see you already have a file named $name\n"; } else { print "P3eharps you'd like to make file called $name\n"; }

Операции для проверка файлов.

ОбозначениеОписание

-rфайл или каталог доступен для чтения
-wфайл или каталог доступен для записи
-xфайл или каталог доступен для выполнения



Операции && и || как управляющие структуры.


Операции && и || в PERL можно рассматривать как управляющие структуры. Возможные варианты:

if(это) { то; } то if это; это && то;

"логическое ИЛИ&quot работает, как оператор unless:

unless (это) { то; }

это || то;



Операции над числами.


2 + 3 5.1 - 2.4 3 * 12 10./3 10%3 2**3

Опериции логического сравнения <, <=, ==, >=, &gt, !=.



Операции над строками.


Канкатенация строк:

"hello" . "world" 'hello world' . "\n" # "hello world\n"

Операции сравнения строк: eq, ne, lt, gt, le, ge.

Операция повторения строки:

"fred" x 3 "barney" x (4+1) (3+2) x 4 #"5555"

Приоритет и ассоциативность опреаций.

Числа в строки и обратно.

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

" 125.45fred" преобразуется в 125.45 # если нет -w "fred" - 0

В противном случае числовое значение конвертируется в строку.

"X" . (4 * 5) # "X20"



Операция замены.


Простая форма операции замены: s/регулярное_выражение/новая_строка/

При всех возможных совпадениях:

$_ = "foot fool buffoon"; s/foo/bar/g; # $_ -> "bart barl bufbarn"

В заменяущей строке производится интерполяция переменных

$_ = "hello, world!"; $new = "goodbye"; s/hello/$new/;

Можно ипользовать сопоставление с образцом

$_ = "this is a test"; s/(\w+)//g;

При помощи операции =~ можно указать другой обьект для операции замены

$which = "this is a test"; $which =~ s/test/quiz/;



Оператор do {} while/until.


do { op_1; op_2; op_3; } while выражение;

Пример:

$stops = 0; do { $stops++; print "Next stop? "; chomp($location = <STDIN&gt); } until $stops &gt 5 || $location eq 'home';



Оператор foreach.


Этот оператор получает список значений и присваивает их по очереди скалярной переменной, выполняя с каждым последующим присваиванием блок кода

foreach $i (@список) { op_1; op_2; op_3; }

Замечание:Скалярная переменная $i - локальна для данного цикла.

Пример:

@a = qw(one two three four five); foreach $b (reverse @a) { print $b; }

Имя скалярной переменной можно опустить. В этом случае, Вы указали имя переменной $_.

@a = qw(one two three four five); foreach (reverse @a) { print ; }

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

@a = (3, 5, 7, 9); foreach $one (@a) { $one *= 3; } # @one = (9, 15, 21, 27);



Оператор if/unless.


if(выражение) { op_1; op_2; op_3; } else { op_1; op_2; op_3; }

Управляющее выражение вычисляется как строковая величина в скалярном контексте (если это уже строка, то ничего не изменится, если это число, то оно преобразуется в строку). Если строка пуста, либо состоит из одного символа "0", то значение выражения - ложь. Все остальное - "истина".

Пример:

print "how old are you? "; $a = <STDIN&gt ; chomp($a); if($a &lt 18) { print "So, you're not old enougt to vote, eh?\n"; } else { print "Old enough! Cool! So go vote!\n"; $voter++; }

Оператор unless:

print "how old are you? "; $a = <STDIN&gt ; chomp($a); unless($a &lt 18) { print "Old enough! Cool! So go vote!\n"; $voter++; }

if(выражение) { op_1; op_2; op_3; } elsif(выражение 2) { op_1; op_2; op_3; } else { op_1; op_2; op_3; }



Оператор while/until.


while(выражение) { op_1; op_2; op_3; }

until(выражение) { op_1; op_2; op_3; }



Определение пользовательской функции.


sub имя { оператор_1; оператор_2; оператор_3; }

sub say_hello { print "hello, world!\n"; }

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