Дескрипторы файлов и проверка файлов.
Открытие и закрытие дескрипторов файлов.
Функция 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>); 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 => "flavors", -VALUES => [qw(mint chocolate cherry vanilla peach)], -LABELS => { mint => "Mightly Mint", chocolate => "Cherished Chocolate", cherry => "Cherry Cherry", vanilla => "Very Vanilla", peach => "Perfectly Peach", }, -SIZE => 3, -MULTIPLE => 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 => "flavors", -LABELS => \%flavors, -VALUES => [keys %flavors], -SIZE => 3, -MULTIPLE => 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> 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"> What is your flavor?<INPUT NAME="favorite" TYPE="text" VALUE="mint"> <P> <INPUT TYPE="submit"> </FORM> </BODY> </HTLM>
Вариант с использованием одного 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> =~ /^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>) { 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>) { 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> ; 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> ; chomp($guess); while(! good_word( $name, $guess )) { print "Wrong, try again. What is a secret word? "; $guess = <STDIN> ; 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> ; 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> ; chomp($guess); while($guess ne $secretword) { print "Wrong, try again. What is a secret word? "; $guess = <STDIN> ; 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 { # создает список всех элементов массива > 100 my(@result); foreach $_ (@_) { if($_ > 100) { push(@result, $_); } } return @result; }
sub bigger_than { # создает список всех элементов массива > 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 (описанные выше образцы характеризуются
" прожорливостью "). Простой способ избежать этого - применение общего множителя.
/x{5,10}/ - найти символ, стоящий перед скобками, повторяющийся от пяти до десяти раз.
/x{5,}/ - найти символ, стоящий перед скобками, повторяющийся от пяти раз.
/x{5}/ - найти символ, стоящий перед скобками, повторяющийся ровно пять раз.
/x{,5}/ - найти символ, стоящий перед скобками, пять раз или менее.
/a.{5}b/ - соответствует букве a, отделенной от буквы b любыми пятью символами.
Если в одном выражении используются два множителя, то правило " прожорливости" дополняется правилом "чем левее, тем прожорливее ". Например:
$_ = "a xxx c xxxxxxxx c xxx d"; /a.*c.*d/;
Первая комбинация ".*" соответствует всем символам до второй буквы 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> ; 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> ; chomp($guess); while(! good_word( $name, $guess )) { print "Wrong, try again. What is a secret word? "; $guess = <STDIN> ; 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>) { chomp($name); $word = <WORDLIST> ; 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> ; 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> ; $i = 0; $correct = "maybe"; while($correct eq "maybe") { if($words[$i] eq "guess) { $correct = "yes"; } elsif($i < 2) { $i = $i + 1; } else { print "Wrong, try again. What is the secret word? "; $guess = <STDIN> ; 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 -> new(); # текущий запрос if($cur -> param("message")) { # мы получили сообщение $cur -> param("data", scalar localtime); # установить текущее время @entries = ($cur); # записать сообщение в массив }
# открыть файл для чтения и записи (с сохранением предыдущего содержимого) open(CHANDLE, "+< $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 -> new(\*CHANDLE); # передать дескриптор файла по ссылке push @entries, $entry; } seek(CHANDLE, 0, 0) || bail("canot rewind $CHATNAME: $!"); foreach $entry (@entries) { $entry -> save(\*CHANDLE); } truncate(CHANDLE, tell(CHANDLE)) || bail("canot truncate $CHATNAME: $!"); close(CHANDLE) || bail("canot close $CHATNAME: $!");
print hr, start_form; print p("Name:", $cur -> textfield(-NAME => "name")); print p("Message:", $cur -> textfield( -NAME => "message", -OVERRIDE => 1, # стирает предыдущее сообщение -SIZE => 50 ) ); print p(submit("send"), reset("clear")); print end_form, hr;
print h2("Prior Messages"); foreach $entry (@entiries) { printf("%s [%s]: %s", $entry -> param("date"), $entry -> param("name"), $entry -> 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> ; 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> ; chomp($guess); while($guess ne $secretword) { print "Wrong, try again. What is a secret word? "; $guess = <STDIN> ; 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> ; 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> ; chomp($guess); while(! good_word( $name, $guess )) { print "Wrong, try again. What is a secret word? "; $guess = <STDIN> ; 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>) { chomp($name); $word = <WORDLIST> ; 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>) { chomp($name); $word = <WORDLIST> ; chomp($word); write; } close(WORDLIST) || die "could not open wordlist: $!"; } format STDOUT = @<<<<<<<<<<<<<< @<<<<<<<< @<<<<<< $filename, $name, $word . format STDOUT_TOP = Page @<< $%
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 @<<<<<<<<<<: last correct guess was @<<< 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 это; это && то;
"логическое ИЛИ" работает, как оператор unless:
unless (это) { то; }
это || то;
Операции над числами.
2 + 3 5.1 - 2.4 3 * 12 10./3 10%3 2**3
Опериции логического сравнения <, <=, ==, >=, >, !=.
Операции над строками.
Канкатенация строк:
"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>); } until $stops > 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> ; chomp($a); if($a < 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> ; chomp($a); unless($a < 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"; }
Определения подпрограмм могут стоять в любом месте текста программы. Определения программ глобальны. В теле функции можно обращаться к переменным, используемым в других частях программы.