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

         

Работа с файлами и каталогами.


Чтение и запись файлов и каталогов является едва ли не главным достоинством Perl. Практически любой Perl-скрипт использует либо запись в файлы,либо поиск определенных строк в файле,либо запись или загрузку файлов в каталоги.

Кратко напомню основные положения:

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

Открыть файл для чтения: open (FILE,"$file");

Открыть файл для записи: open (FILE,">$file");

Открыть файл для добавления: open (FILE,">>$file");

Открыть файл для чтения и добавления: open (FILE,"+<$file");

Где FILE-это дескриптор или описатель файла,т.е. имя,под которым он фигурирует в программе.Может быть любым набом символов,рекомендуется набирать прописными буквами во избежание неоднозначностей.

$file-переменная для файла,содержит обычно имя файла и путь к нему.Предпочтительно объявить эту переменную в начале скрипта.Это удобно,если файл находится где-то глубоко в подкаталогах,к примеру,неудобно все время набирать /usr/local/htdocs/main/pages/file.html.

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

#!/usr/local/bin/perl open (STAT,"$file");#Прочесть одну строку из файла. $count=; close (STAT);

------------------------------------------------- #!/usr/local/bin/perl open (STAT,"$file");#Прочесть файл в массив. @count=; close (STAT);

Что касается каталога,то его тоже можно открывать для чтения командой readdir.Для того,чтобы понять как все это происходит,рассмотрим практические примеры.



Работа со строками в файле


Так как именно те файлы, которые содержат строковую информацию составляют наибольший интерес для, собственно, человека, то и речь сейчас пойдет именно о них.

Для чтения строк из файла используется файловый манипулятор "поставленный" в <>.

Например:

open(FIL,"data.txt"); while() { # делаем что-то с каждой строкой файла }

Если не указано иначе, то внутри такого цикла используется стандартная переменная "$_", а номер строки записывается в "$.". Так как конец строки обозначается спецсимволом, например "\n", для получения самой строки (без эдакого "хвоста") нужно ее усечь функцией chomp.

open(FIL,"data.txt"); while() { chomp; # отрезается спецсимвол от переменной $_ print; # пишем $_ на STDOUT }

Можно прочитать строки в массив:

@strings=; foreach $line (@strings) { print $list; }

Для передвижения по файлу используются функции tell и seek.

open(FIL,"data.txt"); $position=tell(FIL); print "Текущая позиция в файле $position. \n"; seek(FIL,$position+10,1); print "А теперь переместились на 10 байт к концу файла от текущей позиции. \n"; $position=tell(FIL); print "Теперь текущая позиция в файле $position. \n";



Результат:

Текущая позиция в файле 0. А теперь переместились на 10 байт к концу файла. Теперь текущая позиция в файле 10.

Функция tell принимает в качестве параметра файловый манипулятор, а seek берет три параметра. Первый - файловый манипулятор, второй - смещение в байтах, третий - направление смещение. Есть три направления смещения: 0 - от начала файла, 1 - от текущей позиции, 2 - с конца файла.

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

Буду очень благодарен за сообщения о возможных ошибках и неточностях в этой статье.

С уважением. © 2001 Чернявин Александр



Работаем с файлами на Perl


Прислал: Чернявин Александр [ 12.03.2001 @ 03:56 ]
Раздел:: [ Статьи по Perl ]


О том, что такое файл писать я надеюсь ненужно, но думаю нужно подумать над тем, что с ними можно делать, как видно из заголовка статьи, на Perl. Ну, приступим . . .

В этой статье обсудим: Что такое файловые манипуляторы, и с чем их едят Манипуляции с файлом Работа со строками в файле



Regular expressions (регулярные выражения)


А что это за закорючки такие в скрипте - s/^[^\w]{1,3}(\d+)/$1/


Как ими пользоваться?


Как не учитывать регистр в русском тексте? С английским регекспы с ключом i работают, а с русским - нет.


Кто-нибудь может мне по-русски рассказать о операторах: ?:, ?!, ?= и т.д. и когда они используются?



Q: А что это за закорючки такие в скрипте - s/^[^\w]{1,3}(\d+)/$1/

A: Это регулярные выражения, одна из мощнейших возможностей perl. Средства

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

Q: Как ими пользоваться?

A: Этому учатся всю жизнь. Даже книга есть - "Mastering regular

expressions". Также следует прочесть perldoc perlre

А начать можно со следующего: // - поиск

s/// - поиск и замена

tr/// - трансляция

Если мы хотим узнать, нет ли в строке $_ подстроки 'my', мы пишем:

/my/;

Если мы имеем дело не с переменной по умолчанию, а с любой другой, пишем:

$str=~/my/;

Если мы хотим заменить в строке подстроку tree на root, используем поиск и

замену:

$str=~s/tree/root/; В конце выражения могут стоять опции g, i и т.п. g означает проводить замену

не 1 раз, а по всей подстроке. i означает не учитывать регистр символов. В подстроке для поиска можно использовать управляющиесимволы. Есть

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

символиз набора букв, цифр,и т.п., мета-символы, управляющие количеством

символов, и т.п. Hапример, \d в подстроке обозначает любую цифру, \w -

любую букву, \s - пробел, . - любой символ. Стоящая после мета-символа *

означает, что предыдущий символ может повторяться 0 или более раз. + означает

повторение 1 или более раз. То есть, строка вида $str=~s/\s\d+\s/ 1 /g; означает "заменить все числа в строке $str, отделенные пробелами с двух

сторон, на цифру 1, отделенную пробелами". Более подробное описание регулярных выражений, список управляющих символов и

других возможностей смотрите в документации.

Q: Как не учитывать регистр в русском тексте? С английским регекспы с ключом

i работают, а с русским - нет.

A: Hа UNIX'оподобных системах с корректной локализацией (FreeBSD, Linux на

glibc 2.1) это делается так:

use locale;

use POSIX qw (locale_h);

setlocale(LC_CTYPE, 'ru_RU.KOI8-R'); (можно еще выставить переменную окружения export LANG=ru_RU.KOI8-R

тогда будет достаточно вызова use locale; в Perl-скрипте)



Регулярные выражения


Определения

одиночные символы (characters)

классы символов (character classes)

альтернативные шаблоны (alternative match patterns)

квантификаторы (quantifiers)

мнимые символы (assertions)

ссылки на найденный текст (backreferences)

Функции, использующие регулярные выражения

split

grep

map

другие

Как работают регулярные выражения

Логические операции в регулярных выражениях

Вызов функций и подпрограмм

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

Примеры

Рабочие программы, использующие регулярные выражения

Выделение чисел в математической записи

Облегчение поиска работы

Очень простое решение для зеркала новостной ленты

Вывод результатов поиска

Список наиболее употребительных регулярных выражений.



Set permissions:


chmod 755 (-rwxr-xr-x) on all .cgi files.

chmod 666 (-rw-rw-rw-) on all files in the data directory.

chmod 777 (drwxrwxrwx) on the public directory

Тоже многие тут спотыкаются - а что я вытворял!!! Бедный сервер наверное свихнулся - о существовании таких прав доступа, что я ставил, он и не подозревал! Итак, теперь надо установить права доступа: 755 - наивысший приоритет, всем файлам *.cgi, *.pl надо установить его. В инструкциях все пишут - следуйте им! Если есть сомнения, то можно действовать по такому принципу - всем файлам, которые для массового использования ставим 777 , всем исполнительным (*.cgi, *.pl) -755, а тем, которые непонятно какие - 666. Если скрипт не запускается и выдает ошибку (500 Server Errors - очень часто ;-) ), то возможно вы не правильно расставили права, проверьте все (*.cgi, *.pl) в первую очередь! Как эти права расставлять? Опять с помощью FTP клиента: Change File Attributes - и пишете в появившемся окошке необходимые права! Теперь дополнение одного из моих читателей:

................

Было бы неплохо не просто порекомендовать какие права доступа ставить (и для каких файлов), а подробно объяснить, что обозначает каждая буковка в записи "drwxrwxrwx" и цифра в команде "CHMOD" . Это позволило бы новичкам, прочитавшим статью, сэкономить кучу времени и нервов (GK: как он прав!).

Так вот, права доступа определяют: кто и что он может сделать с файлами/папками, размещенными на сервере.

"Кто" подразделяются на три вида:

"Owner" - владелец файла/папки

"Group" - группа, к которой относится владелец

"Everyone" - все остальные пользователи

"Что" подразумевает: какие действия с файлами/папками могут производить Пользователи, Группа или Владелец, а именно:

"Read" - чтение

"Write" - запись

"Execute/Search" - выполнение (для файлов) и поиск (для каталогов).

Число, следующее после команды "chmod xyz имя_файла/папки" расшифровывается следующим образом:


- первая цифра (x) - это права владельца

- вторая (y) - права группы

- третья (z) - права доступа для остальных пользователей.

Каждая цифра - состоит из суммы чисел, которыми эти права обозначаются:

Чтение - число 4

Запись - число 2

Выполнение/поиск - число 1

То есть, если нужно предоставить владельцу право читать, записывать и выполнять файл, то число x получается из суммы 4+2+1 = 7. Если нужно установить права доступа только для чтения и выполнения, то 4+0+1 = 5.

Рассмотрим конкретный пример: что означает это преславутое число 755?

Первая цифра - 7 - право доступа для Владельца (4+2+1) чтение+запись+выполнение.

Вторая цифра - 5 - право доступа для Группы (4+0+1) чтение+выполнение.

Третья цифра - 5 - право доступа для остальных Пользователей (4+0+1) чтение+выполнение. Данное число (755) рекомендуется устанавливать для CGI скриптов, а остальным файлам - 660 (GK: подразумеваются только скриптовые файлы, а не все остальные! Ваши публичные документы имеют доступ 777 - то есть самые широкие права). Также, если есть файлы, в которых хранятся данные "не для чужих глаз" (а именно: шаблоны, файлы регистрации и т.д), то для них я бы порекомендовал установить права доступа - 600 (GK: а часто им ставят 666).

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

d - указывает на то, что это папка. Если стоит "-" - значит это файл.

rwx - права доступа для владельца - "r"ead, "w"rite и e"x"ecute, если вместо какой-либо буквы стоит "-", то это означает, что данное право отсутствует.

Cледующая троица "rwx" аналогична предыдущей, только она определяет права доступа для группы.

И последняя троица "rwx" также определяет права доступа для остальных пользователей. Следовательно, права доступа к файлу 755 выглядят так: "-rwxr-x-r-x"

. .........

Я могу лишь выразить благодарность!


Сheck that the Path to perl is correct. Links defaults with #!/usr/local/bin/perl".


Многие прекращают знакомство со скриптами после подобной фразы. Вас просят убедиться, что правильно прописан путь к perl (а этот путь вы посмотрели - в пред.пункте). Теперь, чем вскрыть скрипт (*.cgi, *.pl)? Можно сделать это в текстовом редакторе, но это не лучший способ для новичков. Я делаю это с помощью PerlBuilder http://www.solutionsoft.com/

(для его функционирования вам придется скачать ActivePerl, его предлагают прям там). Чем он хорош (т.е. Perl Builder)? Проверка синтаксиса, вскрывает все: *.cgi, *.pl, *.html, *.cfg, *.def, *.php, *.html и т.д. Вы сможете проверить работоспособность скрипта прямо у себя дома на компьютере! Правда, особо не обольщайтесь - топ дома вы не запустите, но добьетесь вывода кода html - значит работает!

Итак, открываете файл, там в самом верху строка: #!/usr/bin/perl - исправляете ее на нужную! И все! Если, что-то надо прописать в самом скрипте (опции, например, или пути к папкам(!) - весьма часто встречается) - то внимательно следуйте инструкциям! Если что-то добавляете в код, то перед этим делайте резервную копию - а вдруг? Мы то не программисты!



Шпионская программа


Допустим в Пентагоне нужно ввести авторизованный доступ к данным по определенным правилам:

есть полный файл(data.crypt) всех записей вида(расшифрованный)

London#явка1#доступ#прочее#логин1

Damask#явка2#доступ#прочее#логин2

Peru#явка3#доступ#прочее#логин3

И есть файл скажем для агента agent007.crypt, в котором описан вид доступа только

к определенным данным:

логин1

логин3

т.е. из файла data.crypt нужно выбрать совпадения строк с подстроками файла agent007.crypt и выбрать из data.crypt все параметры спецзадания(-ий). Результат нужно вывести в виде:

<A NAME=\"a\">

aasd

abf

Absc

afgh

<A NAME=\"b\">

bcd

bgh

bfe

и т.д.

т.е. в отсортированном виде. Шпионы тоже люди.

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

#!/usr/bin/perl -wT #ключ -T означает повышенную безопасность, Пентагон все-таки

use strict;

my(@data, @new, $line, $m, @res, @sort, $k, %ha);

my($autor, $pesniya, $position, $u, $n, $im);

open F, "<data.crypt" or die "Err: $!"; @data=<F>; close F;

open F, "<agent007.crypt" or die "Err: $!" @data=<F>; close F;

foreach $line(@new){

foreach $m (@data){push @res, "$m" if($m=~m/^(.*)#$line$/)}

}

@sort=map{$_ -> [1]}

sort{$a->[0] cmp $b->[0]}

map{[/^(.*)#/, $_]}

grep{!$_{$_}++} @res;

foreach $u('a' .. 'z'){

foreach $n(@sort){push @{$ha{$u}}, $n if($n=~m/^$u/)}

}

for $k(sort keys %ha){print "<a href=\"#$k\">$k</a> "}

print "\n<p><center>\n";

for $k(sort keys %ha){

print "<a name=\"$k\"></a><br>\n";

foreach $im(@{$ha{$k}}){

($autor, $pesniya, $position)=split /#/, $im;

print "$autor, $pesniya, $position<br>\n";

}

}

print "</center>";

Разберем работу программы:


foreach $line(@new){

foreach $m (@data){push @res, "$m" if($m=~m/^(.*)#$line$/)}

}

Отсеять из файла data.crypt разрешенные данные для agent007.crypt при помощи сравнения подстрок.

@sort=map{$_ -> [1]}

sort{$a->[0] cmp $b->[0]}

map{[/^(.*)#/, $_]}

grep{!$_{$_}++} @res;

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

foreach $u('a' .. 'z'){

foreach $n(@sort){push @{$ha{$u}}, $n if($n=~m/^$u/)}

}

Создавть хеш массивов, где ключем будет буква, а значением будет массив из строк спецзаданий.

for $k(sort keys %ha){print "<a href=\"#$k\">$k</a> "}

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

for $k(sort keys %ha){

print "<a name=\"$k\"> </a><br>\n";

foreach $im(@{$ha{$k}}){

($autor, $pesniya, $position)=split /#/, $im;

print "$autor, $pesniya, $position<br>\n";

}

}

Вывести массивы, ассоциированные со значениями ключей букв. @{$ha{$k}} - просто обычный массив, доступ к которому зависит от значения ключа $k. Каждый элемент массива стостоит из строки с разделителями #, по нему и разделяет функция split ($autor, $pesniya, $position)=split /#/, $im;


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


П2.1Основные особенности Perl
П2.1.1Введение

П2.2Cтруктуры данных
П2.2.1Скалярные величины
П2.2.2Простые массивы
П2.2.3Ассоциативные массивы

П2.3Синтаксис языка Perl
П2.3.1Основные понятия
П2.3.2Простые операторы
П2.3.3Составные операторы
П2.3.4Операторы языка Perl
П2.3.4.1Термы и операторы списка
П2.3.4.2Оператор ``стрелка''
П2.3.4.3Операторы ++ и - -
П2.3.4.4Экспоненциальный оператор
П2.3.4.5Символьные унарные операторы
П2.3.4.6Операторы связки
П2.3.4.7Бинарные операторы
П2.3.4.8Операторы сдвига
П2.3.4.9Операторы сравнения
П2.3.4.10Операторы эквивалентности
П2.3.4.11Побитовое И, побитовое ИЛИ и Исключающее ИЛИ
П2.3.4.12Логическое И и логическое ИЛИ
П2.3.4.13Оператор диапазона
П2.3.4.14Условный оператор
П2.3.4.15Операторы присваивания
П2.3.4.16Оператор ``запятая''
П2.3.4.17Логическое НЕ
П2.3.4.18Логическое И, ИЛИ и Исключающее ИЛИ
П2.3.4.19Оператор чтения из файла
П2.3.4.20Оператор замены строки
П2.3.4.21Оператор замены множества символов

П2.4Языковые конструкции Perl
П2.4.1Ссылки
П2.4.1.1Основные понятия
П2.4.1.2Символьные ссылки
П2.4.2Регулярные выражения
П2.4.3Зарезервированные переменные
П2.4.4Встроенные функции
П2.4.5Подпрограммы и модули
П2.4.5.1Подпрограммы
П2.4.5.2Пакеты
П2.4.5.3Таблицы символов
П2.4.5.4Конструкторы и деструкторы пакетов
П2.4.5.5Классы
П2.4.5.6Модули

П2.5Объектная ориентация
П2.5.1Объекты
П2.5.2Классы
П2.5.3Методы
П2.5.4Вызов метода
П2.5.5Деструкторы



Сортировки


Сортировка хэша:

%hash = (

'шляпа' => 'серая',

'водка' => 'горькая',

'вобла' => 'вкусная');

foreach $key(sort keys %hash){

print "$key => $hash{$key}\n"; #отсортирует в алфавитном порядке по значениям ключа

}

foreach $value(sort values %hash){

print "$value\n"; #сортировка по значению

}

Сортировка ключей по алфавиту ассоциированных значений:

foreach $key(sort {$hash{$a} cmp $hash{$b}} keys %hash){

print $key, " => ", $hash{$key},"\n";

}

Сортировка по длинне ассоциированных значений:

@massive = sort{length($hash{$a}) length($hash{$b})}

keys %hash;

foreach $key(@massive){

print $key, $hash{$key},"\n";

}

Пример из fido7.ru.perl:

>> Есть хеш массив (слово, частота), необходимо вывести в файл пары

>> (слово,частота) отсортированные по частоте. По ключю - просто, а вот

>> по значению затрудняюсь. Подскахите как проще сделать?

my %hash=('for'=>1000,'to'=>1500,'in'=>2000,'do'=>500);

foreach(sort {$hash{$a} $hash{$b}} keys %hash) {

print $_,'=',$hash{$_},"\n";

}

Как можно хеш положить в строку? Например проблема:

tnc> имеются логи http-gw. Плохость их

tnc> заключается в том, что на каждый запрос в логе появляется 4 строки,

tnc> совершенно не обязательно идущие подряд:

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

не закрыты, а как закроешь - удаляй. Конечно, некий заметный кусок

файла в памяти будет присутствовать, но не полностью же.

Что-нибудь типа

while(<IN>) {

($key, $no, $data) = parse($_); # расковыряли строчку

$buf{$key}-<[$no] = $data; # запихнули в хэш в виде массива

next if $no > 3; # нумеруем, ессно с нуля

analyze($buf{$key}); # обработали

delete $buf{key}; # удалили

}

Слияние хешей выполняется как и слияние массивов:

%hash1 = (

'шляпа' => 'серая',

'водка' => 'горькая',

'вобла' => 'вкусная');

%hash2 = (

'штаны' => 'широкие',

'пиво' => 'темное',

'игрушка' => 'любимая');


%allhash = (%hash1, %hash2);

Чтобы сэкономить память, можно воспользоваться таким кодом:

%hash=();

while (($key, $values) = each(%hash1)){

$hash{$key} = $values;

}

while (($key, $values) = each(%hash2)){

$hash{$key} = $values;

}

Пример работы с хэшем и базой данных из fido7.ru.perl (cм. ответ):

VS> Скажите, можно ли ввести в dbm-базу данных уже заполненный значениями

VS> хеш? Если да, то как?

%hash1=("dfadf", "dfadfd");

dbmopen (%hash, "hash", 0666);

%hash=%hash1;

dbmclose (%hash);

Как передать хэш в функцию? fido7.ru.perl (см. всю дискуссию)

> PK> Вобщем то все передаеться, но использовать его нельзяю

> PK> Hа %_[0] или $_[0]{??} компилер ругаеться.

> %a;

> &f(\%a);

> sub f {

> my $a = $($_[0]){'key'};

> }

> кажется так, мог ошибится в написании. Смысл в передаче ссылки, а не значения.

Это можно сделать также:

1. Неявной передачей ссылки (использование прототипов):

sub f(\%) {

my $a=$_[0]->{'key'};

}

f(%a);

2. Передачей хэша как массива с четным числом

элементов:

sub f {

my $a={@_}->{'key'};

}

f(%a);

Пример использования хеша для транслитерации fido7.ru.perl:

RK> Как сочнить такой tr/../../ (и возможно ли), чтобы

RK> "аб я" -> "abyoya"

RK> Т.е. транслитерацию сделать...

самый простой и топорный вариант - сделать хеш

с соответствиями типа я => ya сплитить строчки и заменять элементы

полученного массива на нужные. что-то на подобие:

@letters = split //, $str;

for (@letters){$_ = $hash{$_}};


Split


Если необходимо разделить данные из STDIN по нужному разделителю, то можно воспользоваться локализацией $/:

sub example_local{ local $/ = undef; @mass= split /pattern/, <>; return 1; } print scalar(@mass);

Можно разделять данные из файла и так:

undef $/; @res=split /pattern/, <F>;

что эквивалентно:

while (<F>) {push @asdf, split}

После split можно ставить вместо запятой и стрелочку:

@mass = split /(\d){4}/ => $file;

В функции сплит можно воспользоваться макисмальным квантификатором *, который в том числе и о символов, позволит разделить строку на символы, которых там нет(в силу того, что * это 0 и более символов), т.е. посимвольно:

@ruru = split /\001*/ => "lalalalalala"; #массив @ruru будет содержать элементы по одной букве.

Если строка состоит из нескольких строк, то можно поставить разделителем и символ начала новой строки:

$str = "asdf\nghjk\nqwer\n"; @lines = split /^/ => $str;

Вобщем, в split можно вставлять любой поиск по шаблону.



Сщетчик посещений


Наверное тоже одним из часто встречающихся приложений CGI являются счетчики посещений. Они стоят практически на каждой страничке, возможно даже и у вас. Но иногда вас не устраивает тот факт, что счетчик лежит где-то в другом месте.Из-за этого скажем невозможно начать счет с произвольного числа.Или еще некоторые счетчики по разному фильтруют 'Reload'. Да и мало ли? Ну а иногда вам хочется просто сделать другой дизайн цифр. То если вы CGI-програмист то возможно имеет смысл написать свой счетчик. И делать с ним что захочется. Вот я так-же написал.....

Скрипт данного счетчика обслужевает несколько счетчиков ,им вы присваиваете идентификаторы. Поэтому вы спокойно можете втыкать независимые счетчики в разные страницы сайта и даже давать это делать друзьям. В общем он прост в использовании:<IMG src="cgi-bin/counter.cgi?id=name">, Где name -любое уникальное имя идентифицирующее счетчик.Вытакже можете задать необязательный параметр dig

который задает количество цифр в счетчике ,Например:

<IMG src="cgi-bin/counter.cgi?id=doom2&dig=9">.

Получится примерно вот так:

.gif'ы в счетчике с прозрачными областями.Что дает дополнительную гибкость к примеру для улучшения внешнего вида с помощью другого фона его иногда имеет смысл запихнуть в "таблицу":

<TABLE><TR><TD bgcolor="white"><IMG src="counter.gif"></TD></TR></TABLE>

Свои данные он пишет примерно в такой файл counter.dat:

doom2 4 127.0.0.1 906992351 quake2 1 127.0.0.1 906992700 quake 3 127.0.0.1 906992668 doom 1 127.0.0.1 906991960

Вы спросите,зачем столько информации? Чтобы отфильтровывать нажатия Reload. Если с одного IP-адреса между заходами промежуток меньше чем 30 секунд,то счетчик не инкрементируется (Так например поступает счетчик в Rambler'е).

Теперь об исходнике.Скрипт получился великоват,потому,что я вместо чтения из файлов решил .gif'ы запихнуть в сам скрипт.Выглядит громоздко , зато пашет как трактор ;))!!




#!/usr/bin/perl #counter.cgi $gifheader="GIF89a"; # Использую 14x16 .gif $digx_size=14; $digy_size=16; $datafile="counter.dat"; ###################################################### $GifData[0]= "GIF89a\x0E\x00\x10\x00\xEF\x00\x00C\x03\x03\x03\xFF\xFF\x2F\x2F\x2F\x8B\x03\x03\x7F\x03\x03\x9B\x03\x03\xA7". "\x03\x03\x5B\x03\x03g\x03\x03\xBF\x03\x03s\x03\x03\xB3\x03\x03O\x03\x03\xCB\x03\x03\xFF\xB7\xB7\x3F\x2B\x1BG3\x23". "\xF3\xA3\xA3\xEB\x97\x97O\x3B\x2B\xF7\xAB\xAB\xDF\x87\x87\xE7\x8F\x8F\xD3ss\xCBkk\xC7cc\xBF\x5B\x5B\xBBW". "W\xDB\x7B\x7B\xAFGG\xA7\x3F\x3F\xA3\x3B\x3B\x9B33\xB3OO\x8F\x2B\x2B\x8B\x23\x23\x83\x1F\x1F\x7F\x1B\x1Bw". "\x17\x17s\x13\x13k\x0F\x0Fg\x0B\x0B_\x07\x07\x5B\x07\x07S\x07\x07\x97\x2F\x2FG\x03\x03C\x03\x03\xFF\xEB\xDF". "\xFF\xE3\xD3\xFF\xDB\xC7\xFF\xD3\xBB\xFF\xCF\xB3\xFF\xC7\xA7\xFF\xBF\x9B\xFF\xBB\x93\xFF\xB3\x83\xF7\xAB\x7B\xEF\xA3s\xE7\x9B". "k\xDF\x93c\xD7\x8B\x5B\xCF\x83S\xCB\x7FO\xBF\x7BK\xB3sG\xABoC\xA3k\x3F\x9Bc\x3B\x8F_7\x87". "W3\x7FS\x2FwO\x2BkG\x27_C\x23S\x3F\x1FK7\x1B\x3F\x2F\x173\x2B\x13\x2B\x23\x0F\xEF\xEF\xEF". "\xE7\xE7\xE7\xDF\xDF\xDF\xDB\xDB\xDB\xD3\xD3\xD3\xCB\xCB\xCB\xC7\xC7\xC7\xBF\xBF\xBF\xB7\xB7\xB7\xB3\xB3\xB3\xAB\xAB\xAB\xA7\xA7". "\xA7\x9F\x9F\x9F\x97\x97\x97\x17\x1F\x07\x2F7\x1F\x0F\x17\x03\x23\x2B\x0F\x07\x07\x07oookkkccc\x5B". "\x5B\x5BWWWOOOGGGCCC\x3B\x3B\x3B777\x13\x13\x13\x27\x27\x27\x23\x23\x23w\xFFo". "o\xEFgg\xDF__\xCFW\x5B\xBFOS\xAFGK\x9F\x3FC\x937\x3F\x83\x2F7s\x2B\x2Fc\x23\x1B\x1B". "\x1B\x1FC\x17\x173\x0F\x13\x23\x0B\x0B\x17\x07\x03\x03\x03\xB7\x9F\x87\xAF\x97\x7F\xA7\x8Fw\x9F\x87o\x9B\x7Fk\x93". "\x7Bc\x8Bs\x5B\x83kW\x7BcOw_KoWCgS\x3F_K7WC3S\x3F\x2F\x9F\x83c". "\x8FwS\x83kKw_\x3FgS3\x5BG\x2BO\x3B\x23C3\x1B\x7B\x7FcosWgkO\x5Bc". "GSW\x3BGO3\x3FG\x2B7\x3F\x27\xFF\xFFs\xEB\xDBW\xD7\xBBC\xC3\x9B\x2F\xAF\x7B\x1F\x9B\x5B\x13\x87". "C\x07s\x2B\x03\xFF\xFF\xFF\xFF\xDB\xDB\xFF\xBB\xBB\xFF\x9B\x9B\xFF\x7B\x7B\xFF__\xFF\x3F\x3F\xFF\x1F\x1F\xFF\x03\x03". "\xEF\x03\x03\xE3\x03\x03\xD7\x03\x03\x83\x83\x83\x0B\x0B\x0B\x7F\x7F\x7F\xFF\xFF\xFFKKK\x17\x0F\x07\x1F\x17\x0Bww". "w\x93\x93\x93\x8B\x8B\x8BO\x03\x03\x27S\x1B\xE7\xE7\xFF\xC7\xC7\xFF\xAB\xAB\xFF\x8F\x8F\xFFss\xFFSS\xFF7". "7\xFF\x1B\x1B\xFF\x03\x03\xFF\x03\x03\xE3\x03\x03\xCB\x03\x03\xB3\x03\x03\x9B\x03\x03\x83\x03\x03k\x03\x03S\xFF\xFF\xFF". "\xFF\xEB\xDB\xFF\xD7\xBB\xFF\xC7\x9B\xFF\xB3\x7B\xFF\xA3\x5B\xFF\x8F\x3B\xFF\x7F\x1B\xF3s\x17\xEBo\x0F\xDFg\x0F\xD7_". "\x0B\xCBW\x07\xC3O\x03\xB7G\x03\xAFC\x03\xFF\xFF\xFF\xFF\xFF\xD7\xFF\xFF\xB3\xFF\xFF\x8F\xFF\xFFk\xFF\xFFG\xFF". "\xFF\x23\xFF\xFF\x03\xA7\x3F\x03\x9F7\x03\x93\x2F\x03\x87\x23\x03O\x3B\x27C\x2F\x1B7\x23\x13\x2F\x1B\x0B\x03\x03S". "\x03\x03G\x03\x03\x3B\x03\x03\x2F\x03\x03\x23\x03\x03\x17\x03\x03\x0B\xBF\xA7\x8F\xFF\x9FC\xFF\xE7K\xFF\x7B\xFF\xFF\x03". "\xFF\xCF\x03\xCF\x9F\x03\x9Bo\x03k\xA7kk\x21\xF9\x04\x01\x00\x00\x01\x00\x2C\x00\x00\x00\x00\x0E\x00\x10\x00\x00\x08". "\x94\x00\x03\x08\x0C\x00\xA0\x60\xC1\x81\x08\x0B\x12\x28\xB0\x60\x40\x81\x83\x03\x01\x1C\x28\xA0\xC0\xE1\x01\x05\x06\x0E\x00\x88". "h\xC0\x00\x81\x01\x03\x10\x20H\xF0P\x00A\x02\x1D\x09\x20\x00\xC0\xE0\x00I\x02\x1B\x01\x60\x1C\x00S\x00\x80\x91". "\x05\x06\x00\xB0y\xC0\x00\xCD\x98\x0A\x16\x14\xA8\x291\xA7N\x82\x0A\x12\xFC\xE4i4\x26\x81\x069w\xCA4\xD0". "\xD0\x29I\x9D6Q6\x7C\xD8\xF0\xE5\xCE\x93\x0B\x3E\xA6L\x60\x60\xA7I\x96\x08\x14\x20\x28\xE0\x91\x80F\x93\x02". "\x0B\x228\x10R\xA3Y\x846\x0D\x9A\x85\x8B0\x80\x80\xBF\x7F\x11\x06\x04\x00\x3B"; $GifData[1]= "GIF89a\x0B\x00\x10\x00\xEF\x00\x00C\x03\x03\x03\xFF\xFF\x2F\x2F\x2F\xBF\x03\x03\x8B\x03\x03\xCB\x03\x03\x9B". "\x03\x03\xA7\x03\x03\xB3\x03\x03\x7F\x03\x03\xD7\x03\x03s\x03\x03G3\x23\x3F\x2B\x1B\x0F\x17\x03O\x3B\x2B\xFF\xB7\xB7". "\xF7\xAB\xAB\xF3\xA3\xA3\xEB\x97\x97\xE7\x8F\x8F\xDF\x87\x87\xDB\x7B\x7B\xD3ss\xCBkk\xC7cc\xBF\x5B\x5B\xBBW". "W\xB3OO\xAFGG\xA7\x3F\x3F\xA3\x3B\x3B\x9B33\x97\x2F\x2F\x8F\x2B\x2B\x8B\x23\x23\x83\x1F\x1F\x7F\x1B\x1Bw". "\x17\x17s\x13\x13k\x0F\x0Fg\x0B\x0B_\x07\x07\x5B\x07\x07S\x07\x07O\x03\x03G\x03\x03C\x03\x03\xFF\xEB\xDF". "\xFF\xE3\xD3\xFF\xDB\xC7\xFF\xD3\xBB\xFF\xCF\xB3\xFF\xC7\xA7\xFF\xBF\x9B\xFF\xBB\x93\xFF\xB3\x83\xF7\xAB\x7B\xEF\xA3s\xE7\x9B". "k\xDF\x93c\xD7\x8B\x5B\xCF\x83S\xCB\x7FO\xBF\x7BK\xB3sG\xABoC\xA3k\x3F\x9Bc\x3B\x8F_7\x87". "W3\x7FS\x2FwO\x2BkG\x27_C\x23S\x3F\x1FK7\x1B\x3F\x2F\x173\x2B\x13\x2B\x23\x0F\xEF\xEF\xEF". "\xE7\xE7\xE7\xDF\xDF\xDF\xDB\xDB\xDB\xD3\xD3\xD3\xCB\xCB\xCB\xC7\xC7\xC7\xBF\xBF\xBF\xB7\xB7\xB7\xB3\xB3\xB3\xAB\xAB\xAB\xA7\xA7". "\xA7\x9F\x9F\x9F\x23\x2B\x0F\x93\x93\x93\x2F7\x1F\x83\x83\x83\x7F\x7F\x7F\x17\x1F\x07oookkkccc\x5B". "\x5B\x5BWWWOOOGGGCCC\x3B\x3B\x3B777\x07\x07\x07\x27\x27\x27\x23\x23\x23w\xFFo". "o\xEFgg\xDF__\xCFW\x5B\xBFOS\xAFGK\x9F\x3FC\x937\x3F\x83\x2F7s\x2B\x2Fc\x23\x0B\x0B". "\x0B\x1FC\x17\x173\x0F\x13\x23\x0B\x0B\x17\x07\x03\x03\x03\xB7\x9F\x87\xAF\x97\x7F\xA7\x8Fw\x9F\x87o\x9B\x7Fk\x93". "\x7Bc\x8Bs\x5B\x83kW\x7BcOw_KoWCgS\x3F_K7WC3S\x3F\x2F\x9F\x83c". "\x8FwS\x83kKw_\x3FgS3\x5BG\x2BO\x3B\x23C3\x1B\x7B\x7FcosWgkO\x5Bc". "GSW\x3BGO3\x3FG\x2B7\x3F\x27\xFF\xFFs\xEB\xDBW\xD7\xBBC\xC3\x9B\x2F\xAF\x7B\x1F\x9B\x5B\x13\x87". "C\x07s\x2B\x03\xFF\xFF\xFF\xFF\xDB\xDB\xFF\xBB\xBB\xFF\x9B\x9B\xFF\x7B\x7B\xFF__\xFF\x3F\x3F\xFF\x1F\x1F\xFF\x03\x03". "\xEF\x03\x03\xE3\x03\x03www\x13\x13\x13\x1B\x1B\x1B\xFF\xFF\xFFKKK\x17\x0F\x07\x1F\x17\x0B\x97\x97\x97\x8B\x8B". "\x8Bg\x03\x03\x5B\x03\x03O\x03\x03\x27S\x1B\xE7\xE7\xFF\xC7\xC7\xFF\xAB\xAB\xFF\x8F\x8F\xFFss\xFFSS\xFF7". "7\xFF\x1B\x1B\xFF\x03\x03\xFF\x03\x03\xE3\x03\x03\xCB\x03\x03\xB3\x03\x03\x9B\x03\x03\x83\x03\x03k\x03\x03S\xFF\xFF\xFF". "\xFF\xEB\xDB\xFF\xD7\xBB\xFF\xC7\x9B\xFF\xB3\x7B\xFF\xA3\x5B\xFF\x8F\x3B\xFF\x7F\x1B\xF3s\x17\xEBo\x0F\xDFg\x0F\xD7_". "\x0B\xCBW\x07\xC3O\x03\xB7G\x03\xAFC\x03\xFF\xFF\xFF\xFF\xFF\xD7\xFF\xFF\xB3\xFF\xFF\x8F\xFF\xFFk\xFF\xFFG\xFF". "\xFF\x23\xFF\xFF\x03\xA7\x3F\x03\x9F7\x03\x93\x2F\x03\x87\x23\x03O\x3B\x27C\x2F\x1B7\x23\x13\x2F\x1B\x0B\x03\x03S". "\x03\x03G\x03\x03\x3B\x03\x03\x2F\x03\x03\x23\x03\x03\x17\x03\x03\x0B\xBF\xA7\x8F\xFF\x9FC\xFF\xE7K\xFF\x7B\xFF\xFF\x03". "\xFF\xCF\x03\xCF\x9F\x03\x9Bo\x03k\xA7kk\x21\xF9\x04\x01\x00\x00\x01\x00\x2C\x00\x00\x00\x00\x0B\x00\x10\x00\x00\x08". "g\x00\x03\x08\x04\x40\xB0\x20\x00\x81\x01\x00\x1C\x40P\xA0\x80\x82\x03\x00\x04\x24\x24p\xC0\xC0\x80\x01\x08\x08D\x04". "\x40\x80\xE2\x81\x86\x034\x0A0\xC8\xB0\x40\xC8\x88\x01\x04\x8C\xFC\xD8P\x24B\x85\x03Z\xA2\x1Ch\xF1\xA2K\x9A". "\x17OJ\xC4isf\xC2\x9A\x03\x12\xF8\x04\x60\x00\x81Q\xA1\x3B\x7F\x22\xB8\x88\xF4\x25\x01\x03\x1D\x17\x0C5H". "0iJ\x95X\x05\x04\x04\x00\x3B"; $GifData[2]= "GIF89a\x0E\x00\x10\x00\xEF\x00\x00C\x03\x03\x03\xFF\xFF\x2F\x2F\x2F\x7F\x03\x03\xA7\x03\x03\x9B\x03\x03\xB3". "\x03\x03\xBF\x03\x03\x8B\x03\x03\xEF\x03\x03\xCB\x03\x03s\x03\x03\xD7\x03\x03\xE3\x03\x03g\x03\x03\xFF\xB7\xB7\xF7\xAB\xAB". "\xF3\xA3\xA3\x3F\x2B\x1B\xEB\x97\x97\xE7\x8F\x8F\xDF\x87\x87\xDB\x7B\x7B\xD3ss\xCBkk\xC7cc\xBF\x5B\x5B\xBBW". "W\xB3OO\xAFGG\xA7\x3F\x3F\xA3\x3B\x3B\x9B33\x97\x2F\x2F\x8F\x2B\x2B\x8B\x23\x23\x83\x1F\x1F\x7F\x1B\x1Bw". "\x17\x17s\x13\x13k\x0F\x0Fg\x0B\x0B_\x07\x07\x5B\x07\x07S\x07\x07O\x03\x03G\x03\x03C\x03\x03\xFF\xEB\xDF". "\xFF\xE3\xD3\xFF\xDB\xC7\xFF\xD3\xBB\xFF\xCF\xB3\xFF\xC7\xA7\xFF\xBF\x9B\xFF\xBB\x93\xFF\xB3\x83\xF7\xAB\x7B\xEF\xA3s\xE7\x9B". "k\xDF\x93c\xD7\x8B\x5B\xCF\x83S\xCB\x7FO\xBF\x7BK\xB3sG\xABoC\xA3k\x3F\x9Bc\x3B\x8F_7\x87". "W3\x7FS\x2FwO\x2BkG\x27_C\x23S\x3F\x1FK7\x1B\x3F\x2F\x173\x2B\x13\x2B\x23\x0F\xEF\xEF\xEF". "\xE7\xE7\xE7\xDF\xDF\xDF\xDB\xDB\xDB\xD3\xD3\xD3\xCB\xCB\xCB\xC7\xC7\xC7\xBF\xBF\xBF\xB7\xB7\xB7\xB3\xB3\xB3\xAB\xAB\xAB\xA7\xA7". "\xA7\x9F\x9F\x9F\x2F7\x1FO\x3B\x2B\x0F\x17\x03G3\x23\x7F\x7F\x7F\x23\x2B\x0Foookkkccc\x5B". "\x5B\x5BWWWOOOGGGCCC\x3B\x3B\x3B777\x0B\x0B\x0B\x27\x27\x27\x23\x23\x23w\xFFo". "o\xEFgg\xDF__\xCFW\x5B\xBFOS\xAFGK\x9F\x3FC\x937\x3F\x83\x2F7s\x2B\x2Fc\x23\x13\x13". "\x13\x1FC\x17\x173\x0F\x13\x23\x0B\x0B\x17\x07\x03\x03\x03\xB7\x9F\x87\xAF\x97\x7F\xA7\x8Fw\x9F\x87o\x9B\x7Fk\x93". "\x7Bc\x8Bs\x5B\x83kW\x7BcOw_KoWCgS\x3F_K7WC3S\x3F\x2F\x9F\x83c". "\x8FwS\x83kKw_\x3FgS3\x5BG\x2BO\x3B\x23C3\x1B\x7B\x7FcosWgkO\x5Bc". "GSW\x3BGO3\x3FG\x2B7\x3F\x27\xFF\xFFs\xEB\xDBW\xD7\xBBC\xC3\x9B\x2F\xAF\x7B\x1F\x9B\x5B\x13\x87". "C\x07s\x2B\x03\xFF\xFF\xFF\xFF\xDB\xDB\xFF\xBB\xBB\xFF\x9B\x9B\xFF\x7B\x7B\xFF__\xFF\x3F\x3F\xFF\x1F\x1F\xFF\x03\x03". "\x17\x1F\x07\x83\x83\x83\x07\x07\x07www\x1B\x1B\x1B\xFF\xFF\xFFKKK\x17\x0F\x07\x1F\x17\x0B\x97\x97\x97\x93\x93". "\x93\x8B\x8B\x8B\x5B\x03\x03O\x03\x03\x27S\x1B\xE7\xE7\xFF\xC7\xC7\xFF\xAB\xAB\xFF\x8F\x8F\xFFss\xFFSS\xFF7". "7\xFF\x1B\x1B\xFF\x03\x03\xFF\x03\x03\xE3\x03\x03\xCB\x03\x03\xB3\x03\x03\x9B\x03\x03\x83\x03\x03k\x03\x03S\xFF\xFF\xFF". "\xFF\xEB\xDB\xFF\xD7\xBB\xFF\xC7\x9B\xFF\xB3\x7B\xFF\xA3\x5B\xFF\x8F\x3B\xFF\x7F\x1B\xF3s\x17\xEBo\x0F\xDFg\x0F\xD7_". "\x0B\xCBW\x07\xC3O\x03\xB7G\x03\xAFC\x03\xFF\xFF\xFF\xFF\xFF\xD7\xFF\xFF\xB3\xFF\xFF\x8F\xFF\xFFk\xFF\xFFG\xFF". "\xFF\x23\xFF\xFF\x03\xA7\x3F\x03\x9F7\x03\x93\x2F\x03\x87\x23\x03O\x3B\x27C\x2F\x1B7\x23\x13\x2F\x1B\x0B\x03\x03S". "\x03\x03G\x03\x03\x3B\x03\x03\x2F\x03\x03\x23\x03\x03\x17\x03\x03\x0B\xBF\xA7\x8F\xFF\x9FC\xFF\xE7K\xFF\x7B\xFF\xFF\x03". "\xFF\xCF\x03\xCF\x9F\x03\x9Bo\x03k\xA7kk\x21\xF9\x04\x01\x00\x00\x01\x00\x2C\x00\x00\x00\x00\x0E\x00\x10\x00\x00\x08". "\x8F\x00\x03\x00\x18Hp\x60\x80\x83\x08\x01\x20\x20\xC0\x40\x81\x02\x03\x04\x1C\x00\x40\x28p\xC0B\x03\x05\x0AX\x1C". "0\xF1\x20\x80\x05\x08\x16\x0C\x18\xB0\x20\xE3\x01\x8E\x1E\x0B\x0E\x1C\x40\xE0\x40\x01\x00\x02\x0E\x0AP9\xC0\x80\x82\x97". "1\x2B\x2Ah\xD0\xF0\xC0\x01\x03\x1Cc\x02\x18P\x00\x28\x01\x03\x3E\x83\xCE\x24z\xD4\x81\xC5\x900\x85b\xD4\xA8". "R\x40N\x00\x10\x09pT\xD9\x11\x00\x81\xA3\x04\x12\x88\x15k\x00\xA6\xC0\xAF\x07Z\xFAd\xD0\x00g\xC5\x91\x20". "\x11\x14\xF8\x8A\xC0\x2CW\xAE9\xAD\xEA\xDD\xAB7\x40\x40\x00\x3B"; $GifData[3]= "GIF89a\x0E\x00\x10\x00\xEF\x00\x00C\x03\x03\x03\xFF\xFF\x2F\x2F\x2Fs\x03\x03\xBF\x03\x03\xB3\x03\x03\xE3". "\x03\x03\xCB\x03\x03\x8B\x03\x03\x9B\x03\x03\xD7\x03\x03\xEF\x03\x03\xA7\x03\x03g\x03\x03\x7F\x03\x03G3\x23\xFF\xB7\xB7". "\xF7\xAB\xAB\xF3\xA3\xA3\xEB\x97\x97\xE7\x8F\x8F\xDF\x87\x87\xDB\x7B\x7B\xD3ss\xCBkk\xC7cc\xBF\x5B\x5B\xBBW". "W\xB3OO\xAFGG\xA7\x3F\x3F\xA3\x3B\x3BO\x3B\x2B\x3F\x2B\x1B\x8F\x2B\x2B\x8B\x23\x23\x83\x1F\x1F\x7F\x1B\x1Bw". "\x17\x17s\x13\x13k\x0F\x0Fg\x0B\x0B_\x07\x07\x5B\x07\x07S\x07\x07O\x03\x03G\x03\x03C\x03\x03\xFF\xEB\xDF". "\xFF\xE3\xD3\xFF\xDB\xC7\xFF\xD3\xBB\x9B33\x97\x2F\x2F\xFF\xCF\xB3\xFF\xBB\x93\xFF\xB3\x83\xF7\xAB\x7B\xEF\xA3s\xE7\x9B". "k\xDF\x93c\xD7\x8B\x5B\xCF\x83S\xCB\x7FO\xBF\x7BK\xB3sG\xABoC\xA3k\x3F\x9Bc\x3B\x8F_7\x87". "W3\x7FS\x2FwO\x2BkG\x27_C\x23S\x3F\x1FK7\x1B\x3F\x2F\x173\x2B\x13\x2B\x23\x0F\xEF\xEF\xEF". "\xE7\xE7\xE7\xDF\xDF\xDF\xDB\xDB\xDB\xD3\xD3\xD3\xCB\xCB\xCB\xC7\xC7\xC7\xBF\xBF\xBF\xB7\xB7\xB7\xB3\xB3\xB3\xAB\xAB\xAB\xA7\xA7". "\xA7\x9F\x9F\x9F\xFF\xC7\xA7\xFF\xBF\x9B\xFF\xFF\xFF\x83\x83\x83\x17\x1F\x07\x0F\x17\x03oookkkccc\x5B". "\x5B\x5BWWWOOOGGGCCC\x3B\x3B\x3B777\x17\x0F\x07\x27\x27\x27\x23\x23\x23w\xFFo". "o\xEFgg\xDF__\xCFW\x5B\xBFOS\xAFGK\x9F\x3FC\x937\x3F\x83\x2F7s\x2B\x2Fc\x23\x1F\x17". "\x0B\x1FC\x17\x173\x0F\x13\x23\x0B\x0B\x17\x07\x03\x03\x03\xB7\x9F\x87\xAF\x97\x7F\xA7\x8Fw\x9F\x87o\x9B\x7Fk\x93". "\x7Bc\x8Bs\x5B\x83kW\x7BcOw_KoWCgS\x3F_K7WC3S\x3F\x2F\x9F\x83c". "\x8FwS\x83kKw_\x3FgS3\x5BG\x2BO\x3B\x23C3\x1B\x7B\x7FcosWgkO\x5Bc". "GSW\x3BGO3\x3FG\x2B7\x3F\x27\xFF\xFFs\xEB\xDBW\xD7\xBBC\xC3\x9B\x2F\xAF\x7B\x1F\x9B\x5B\x13\x87". "C\x07s\x2B\x03\xFF\xFF\xFF\xFF\xDB\xDB\xFF\xBB\xBB\xFF\x9B\x9B\xFF\x7B\x7B\xFF__\xFF\x3F\x3F\xFF\x1F\x1F\xFF\x03\x03". "\x7F\x7F\x7F\x23\x2B\x0F\x2F7\x1F\x07\x07\x07\x0B\x0B\x0B\x13\x13\x13www\x1B\x1B\x1BKKK\x97\x97\x97\x93\x93". "\x93\x8B\x8B\x8B\x5B\x03\x03O\x03\x03\x27S\x1B\xE7\xE7\xFF\xC7\xC7\xFF\xAB\xAB\xFF\x8F\x8F\xFFss\xFFSS\xFF7". "7\xFF\x1B\x1B\xFF\x03\x03\xFF\x03\x03\xE3\x03\x03\xCB\x03\x03\xB3\x03\x03\x9B\x03\x03\x83\x03\x03k\x03\x03S\xFF\xFF\xFF". "\xFF\xEB\xDB\xFF\xD7\xBB\xFF\xC7\x9B\xFF\xB3\x7B\xFF\xA3\x5B\xFF\x8F\x3B\xFF\x7F\x1B\xF3s\x17\xEBo\x0F\xDFg\x0F\xD7_". "\x0B\xCBW\x07\xC3O\x03\xB7G\x03\xAFC\x03\xFF\xFF\xFF\xFF\xFF\xD7\xFF\xFF\xB3\xFF\xFF\x8F\xFF\xFFk\xFF\xFFG\xFF". "\xFF\x23\xFF\xFF\x03\xA7\x3F\x03\x9F7\x03\x93\x2F\x03\x87\x23\x03O\x3B\x27C\x2F\x1B7\x23\x13\x2F\x1B\x0B\x03\x03S". "\x03\x03G\x03\x03\x3B\x03\x03\x2F\x03\x03\x23\x03\x03\x17\x03\x03\x0B\xBF\xA7\x8F\xFF\x9FC\xFF\xE7K\xFF\x7B\xFF\xFF\x03". "\xFF\xCF\x03\xCF\x9F\x03\x9Bo\x03k\xA7kk\x21\xF9\x04\x01\x00\x00\x01\x00\x2C\x00\x00\x00\x00\x0E\x00\x10\x00\x00\x08". "\x85\x00\x01\x08\x1C80\x80A\x83\x00\x10\x280\xC0\xF0\x00\x81\x01\x02\x0F\x02p\xC0\xA0\x40\x01\x02\x16\x19\x24h". "\x00\x00\xE1\x80\x8F\x20\x07\x10\x20\x90\x00\x80\x80\x00\x04\x09\x128\x90\x00\xA2A\x01\x02R\xAEd\x80\xC0\xA4\xC4\x03". "\x0D\x09\x28\x20P\xF3\x24\xC2\x91\x16u\xF2\xB4\xE9\xF1\x23\x82\x02\x06\x86\xFAD\xA9\xD2\x40\x81\x9E\x29\x07\x12H\xCA". "1f\x81\x05X\x15\x1Cp\xA8\xA0\x24L\x00\x09\x82Z\xBC\xB8\xD1\x26\x80\x90\x21\x05\xC2d\x1A\xD5\xE4\xDA\x970". "\xE3\xC6\x3D\x18\x20\x20\x00\x3B"; $GifData[4]= "GIF89a\x0E\x00\x10\x00\xEF\x00\x00C\x03\x03\x03\xFF\xFF\x2F\x2F\x2F\x7F\x03\x03s\x03\x03\x8B\x03\x03g". "\x03\x03\xA7\x03\x03\x9B\x03\x03\xB3\x03\x03\xBF\x03\x03\xD7\x03\x03\xE3\x03\x03\xEF\x03\x03S\x07\x07\x5B\x03\x03C\x03\x03". "\xCBkk\xEB\x97\x97\xE7\x8F\x8F\xDF\x87\x87\xF7\xAB\xAB\xFF\xB7\xB7\xDB\x7B\x7B\xF3\xA3\xA3\xC7cc\xBF\x5B\x5B\xBBW". "W\xB3OO\xD3ss\xA7\x3F\x3F\xAFGG\x9B33\x97\x2F\x2F\x8F\x2B\x2B\x8B\x23\x23\x83\x1F\x1F\x7F\x1B\x1Bw". "\x17\x17s\x13\x13k\x0F\x0Fg\x0B\x0B_\x07\x07\x5B\x07\x07\xA3\x3B\x3BO\x03\x03G\x03\x03\x83\x83\x83\xFF\xEB\xDF". "\xFF\xE3\xD3\xFF\xDB\xC7\xFF\xD3\xBB\xFF\xCF\xB3\xFF\xC7\xA7\xFF\xBF\x9B\xFF\xBB\x93\xFF\xB3\x83\xF7\xAB\x7B\xEF\xA3s\xE7\x9B". "k\xDF\x93c\xD7\x8B\x5B\xCF\x83S\xCB\x7FO\xBF\x7BK\xB3sG\xABoC\xA3k\x3F\x9Bc\x3B\x8F_7\x87". "W3\x7FS\x2FwO\x2BkG\x27_C\x23S\x3F\x1FK7\x1B\x3F\x2F\x173\x2B\x13\x2B\x23\x0F\xEF\xEF\xEF". "\xE7\xE7\xE7\xDF\xDF\xDF\xDB\xDB\xDB\xD3\xD3\xD3\xCB\xCB\xCB\xC7\xC7\xC7\xBF\xBF\xBF\xB7\xB7\xB7\xB3\xB3\xB3\xAB\xAB\xAB\xA7\xA7". "\xA7\x9F\x9F\x9F\x97\x97\x97\x0F\x17\x03G3\x23\x3F\x2B\x1B\x7F\x7F\x7FwwwoooO\x3B\x2Bccc\x5B". "\x5B\x5BWWWOOOGGGCCC\x3B\x3B\x3B777\x23\x2B\x0F\x27\x27\x27\x23\x23\x23w\xFFo". "o\xEFgg\xDF__\xCFW\x5B\xBFOS\xAFGK\x9F\x3FC\x937\x3F\x83\x2F7s\x2B\x2Fc\x23\x2F7". "\x1F\x1FC\x17\x173\x0F\x13\x23\x0B\x0B\x17\x07\x03\x03\x03\xB7\x9F\x87\xAF\x97\x7F\xA7\x8Fw\x9F\x87o\x9B\x7Fk\x93". "\x7Bc\x8Bs\x5B\x83kW\x7BcOw_KoWCgS\x3F_K7WC3S\x3F\x2F\x9F\x83c". "\x8FwS\x83kKw_\x3FgS3\x5BG\x2BO\x3B\x23C3\x1B\x7B\x7FcosWgkO\x5Bc". "GSW\x3BGO3\x3FG\x2B7\x3F\x27\xFF\xFFs\xEB\xDBW\xD7\xBBC\xC3\x9B\x2F\xAF\x7B\x1F\x9B\x5B\x13\x87". "C\x07s\x2B\x03\xFF\xFF\xFF\xFF\xDB\xDB\xFF\xBB\xBB\xFF\x9B\x9B\xFF\x7B\x7B\xFF__\xFF\x3F\x3F\xFF\x1F\x1F\xFF\x03\x03". "\x17\x1F\x07kkk\x07\x07\x07\xCB\x03\x03\x0B\x0B\x0B\x13\x13\x13\x1B\x1B\x1B\xFF\xFF\xFFKKK\x17\x0F\x07\x1F\x17". "\x0B\x93\x93\x93\x8B\x8B\x8BO\x03\x03\x27S\x1B\xE7\xE7\xFF\xC7\xC7\xFF\xAB\xAB\xFF\x8F\x8F\xFFss\xFFSS\xFF7". "7\xFF\x1B\x1B\xFF\x03\x03\xFF\x03\x03\xE3\x03\x03\xCB\x03\x03\xB3\x03\x03\x9B\x03\x03\x83\x03\x03k\x03\x03S\xFF\xFF\xFF". "\xFF\xEB\xDB\xFF\xD7\xBB\xFF\xC7\x9B\xFF\xB3\x7B\xFF\xA3\x5B\xFF\x8F\x3B\xFF\x7F\x1B\xF3s\x17\xEBo\x0F\xDFg\x0F\xD7_". "\x0B\xCBW\x07\xC3O\x03\xB7G\x03\xAFC\x03\xFF\xFF\xFF\xFF\xFF\xD7\xFF\xFF\xB3\xFF\xFF\x8F\xFF\xFFk\xFF\xFFG\xFF". "\xFF\x23\xFF\xFF\x03\xA7\x3F\x03\x9F7\x03\x93\x2F\x03\x87\x23\x03O\x3B\x27C\x2F\x1B7\x23\x13\x2F\x1B\x0B\x03\x03S". "\x03\x03G\x03\x03\x3B\x03\x03\x2F\x03\x03\x23\x03\x03\x17\x03\x03\x0B\xBF\xA7\x8F\xFF\x9FC\xFF\xE7K\xFF\x7B\xFF\xFF\x03". "\xFF\xCF\x03\xCF\x9F\x03\x9Bo\x03k\xA7kk\x21\xF9\x04\x01\x00\x00\x01\x00\x2C\x00\x00\x00\x00\x0E\x00\x10\x00\x00\x08". "\x8B\x00\x01\x08\x1C\x18\x60\x20A\x00\x05\x184H\x00\xA0\xE0\x81\x05\x0B\x10\x00\x10\x00\x60\x40\x82\x04\x05\x1AV\x3C". "\x80\x20\x23\xC5\x01\x07\x0E\x0C\xD08\x00A\xC7\x89\x08C\x8E\x2C8\xA0\x40\x81\x91\x14\x0B\x98\x1C\x29\x90\x40K\x98". "\x08\x2F\x16H\x10\x92\x80O\x9C\x05\x14\x28\xE0\xF8r\x80O\x03\x28\x83\xF2\x1C\x60\xC0\xC0O\xA4\x14\x0D\x0Et\xCA". "tb\x80\x00\x02\xB2f\x05\x40\x95\x80\xD5\xAB\x60\x0BR\x85\x1A\x16\x2CW\x02\x05\xBC\x0A\x28\x7B\x15\x80\x83\x07\x04". "\x0C\x40X\xCBV\xEAW\xB6Z\xB5\x06\x04\x00\x3B"; $GifData[5]= "GIF89a\x0E\x00\x10\x00\xEF\x00\x00C\x03\x03\x2F\x2F\x2F\x03\xFF\xFF\x7F\x03\x03\x9B\x03\x03\xA7\x03\x03\x8B". "\x03\x03s\x03\x03\xBF\x03\x03\xB3\x03\x03\xD7\x03\x03\xCB\x03\x03\xEF\x03\x03\xE3\x03\x03\x3F\x2B\x1B\x23\x2B\x0F\xFF\xB7\xB7". "\xF7\xAB\xAB\xF3\xA3\xA3\xEB\x97\x97\xE7\x8F\x8F\xDF\x87\x87\xDB\x7B\x7B\xD3ss\xCBkk\xC7cc\xBF\x5B\x5B\xBBW". "W\xB3OO\xAFGG\xA7\x3F\x3F\xA3\x3B\x3B\x9B33\x97\x2F\x2F\x8F\x2B\x2B\x8B\x23\x23\x83\x1F\x1F\x7F\x1B\x1Bw". "\x17\x17s\x13\x13k\x0F\x0Fg\x0B\x0B_\x07\x07\x5B\x07\x07S\x07\x07O\x03\x03G\x03\x03C\x03\x03\xFF\xEB\xDF". "\xFF\xE3\xD3\xFF\xDB\xC7\xFF\xD3\xBB\xFF\xCF\xB3\xFF\xC7\xA7\xFF\xBF\x9B\xFF\xBB\x93\xFF\xB3\x83\xF7\xAB\x7B\xEF\xA3s\xE7\x9B". "k\xDF\x93c\xD7\x8B\x5B\xCF\x83S\xCB\x7FO\xBF\x7BK\xB3sG\xABoC\xA3k\x3F\x9Bc\x3B\x8F_7\x87". "W3\x7FS\x2FwO\x2BkG\x27_C\x23S\x3F\x1FK7\x1B\x3F\x2F\x173\x2B\x13\x2B\x23\x0F\xEF\xEF\xEF". "\xE7\xE7\xE7\xDF\xDF\xDF\xDB\xDB\xDB\xD3\xD3\xD3\xCB\xCB\xCB\xC7\xC7\xC7\xBF\xBF\xBF\xB7\xB7\xB7\xB3\xB3\xB3\xAB\xAB\xAB\xA7\xA7". "\xA7\x9F\x9F\x9F\x1B\x1B\x1B\x17\x1F\x07O\x3B\x2BG3\x23\x7F\x7F\x7Fwwwoookkkccc\x5B". "\x5B\x5BWWWOOOGGGCCC\x3B\x3B\x3B777KKK\x27\x27\x27\x23\x23\x23w\xFFo". "o\xEFgg\xDF__\xCFW\x5B\xBFOS\xAFGK\x9F\x3FC\x937\x3F\x83\x2F7s\x2B\x2Fc\x23\x17\x0F". "\x07\x1FC\x17\x173\x0F\x13\x23\x0B\x0B\x17\x07\x03\x03\x03\xB7\x9F\x87\xAF\x97\x7F\xA7\x8Fw\x9F\x87o\x9B\x7Fk\x93". "\x7Bc\x8Bs\x5B\x83kW\x7BcOw_KoWCgS\x3F_K7WC3S\x3F\x2F\x9F\x83c". "\x8FwS\x83kKw_\x3FgS3\x5BG\x2BO\x3B\x23C3\x1B\x7B\x7FcosWgkO\x5Bc". "GSW\x3BGO3\x3FG\x2B7\x3F\x27\xFF\xFFs\xEB\xDBW\xD7\xBBC\xC3\x9B\x2F\xAF\x7B\x1F\x9B\x5B\x13\x87". "C\x07s\x2B\x03\xFF\xFF\xFF\xFF\xDB\xDB\xFF\xBB\xBB\xFF\x9B\x9B\xFF\x7B\x7B\xFF__\xFF\x3F\x3F\xFF\x1F\x1F\xFF\x03\x03". "\x0F\x17\x03\x0B\x0B\x0B\x2F7\x1F\x13\x13\x13\x07\x07\x07\x93\x93\x93\xFF\xFF\xFF\x1F\x17\x0B\x83\x83\x83\x97\x97\x97\x8B\x8B". "\x8Bg\x03\x03\x5B\x03\x03O\x03\x03\x27S\x1B\xE7\xE7\xFF\xC7\xC7\xFF\xAB\xAB\xFF\x8F\x8F\xFFss\xFFSS\xFF7". "7\xFF\x1B\x1B\xFF\x03\x03\xFF\x03\x03\xE3\x03\x03\xCB\x03\x03\xB3\x03\x03\x9B\x03\x03\x83\x03\x03k\x03\x03S\xFF\xFF\xFF". "\xFF\xEB\xDB\xFF\xD7\xBB\xFF\xC7\x9B\xFF\xB3\x7B\xFF\xA3\x5B\xFF\x8F\x3B\xFF\x7F\x1B\xF3s\x17\xEBo\x0F\xDFg\x0F\xD7_". "\x0B\xCBW\x07\xC3O\x03\xB7G\x03\xAFC\x03\xFF\xFF\xFF\xFF\xFF\xD7\xFF\xFF\xB3\xFF\xFF\x8F\xFF\xFFk\xFF\xFFG\xFF". "\xFF\x23\xFF\xFF\x03\xA7\x3F\x03\x9F7\x03\x93\x2F\x03\x87\x23\x03O\x3B\x27C\x2F\x1B7\x23\x13\x2F\x1B\x0B\x03\x03S". "\x03\x03G\x03\x03\x3B\x03\x03\x2F\x03\x03\x23\x03\x03\x17\x03\x03\x0B\xBF\xA7\x8F\xFF\x9FC\xFF\xE7K\xFF\x7B\xFF\xFF\x03". "\xFF\xCF\x03\xCF\x9F\x03\x9Bo\x03k\xA7kk\x21\xF9\x04\x01\x00\x00\x02\x00\x2C\x00\x00\x00\x00\x0E\x00\x10\x00\x00\x08". "\x8D\x00\x01\x08\x1CHP\xA0\x00\x01\x00\x0E\x20\x28\x90\x60\x81\x82\x87\x05\x0C\x00\x08\x80P\xE1\x00\x02\x04\x06\x18\x88". "8\x60\x22\xC2\x01\x08\x08\x1C\x18p\xA0\xA4\x81\x03\x1E\x01\x10\x40\xD0\xB1\xA0\x40\x8A\x2A\x17\xB4\x24\x18\xA0\xE6\xC7\x04". "\x08\x1C6P\xC0\x12\xC0\xC1\x8A\x08\x10\x24\x88\xC80\xA3\xCF\x8A\x07\x0C\x18\x20i\x60\xA8\xD1\x835\x0B\x5E\x24\x90". "\x60\xA2K\x81\x03\x0A0\xB4\x9A\x80\x81W\x06\x0B6\x260\x1A\x40\xE5\xCE\xA0\x18\x0B\xF4\x8C\xBA\xB1\x00\x01\xA5\x24". "\x3B\xDA\xBC\xFA\xD2\x26\xD4\x9Ax\xF1\xFE\x14\x10\x10\x00\x3B"; $GifData[6]= "GIF89a\x0E\x00\x10\x00\xEF\x00\x00C\x03\x03\x03\xFF\xFF\x2F\x2F\x2F\xBF\x03\x03s\x03\x03\x8B\x03\x03\x9B". "\x03\x03\xA7\x03\x03\xB3\x03\x03g\x03\x03\xCB\x03\x03\xD7\x03\x03\x7F\x03\x03\xE3\x03\x03\xFF\xB7\xB7\x3F\x2B\x1B\xF7\xAB\xAB". "G3\x23\xF3\xA3\xA3\xEB\x97\x97\xE7\x8F\x8F\xDF\x87\x87\xDB\x7B\x7B\xD3ss\xCBkk\xC7cc\xBF\x5B\x5B\xBBW". "W\xB3OO\xAFGG\xA7\x3F\x3F\xA3\x3B\x3B\x9B33\x97\x2F\x2F\x8F\x2B\x2B\x8B\x23\x23\x83\x1F\x1F\x7F\x1B\x1Bw". "\x17\x17s\x13\x13k\x0F\x0Fg\x0B\x0B_\x07\x07\x5B\x07\x07S\x07\x07O\x03\x03G\x03\x03C\x03\x03\xFF\xEB\xDF". "\xFF\xE3\xD3\xFF\xDB\xC7\xFF\xD3\xBB\xFF\xCF\xB3\xFF\xC7\xA7\xFF\xBF\x9B\xFF\xBB\x93\xFF\xB3\x83\xF7\xAB\x7B\xEF\xA3s\xE7\x9B". "k\xDF\x93c\xD7\x8B\x5B\xCF\x83S\xCB\x7FO\xBF\x7BK\xB3sG\xABoC\xA3k\x3F\x9Bc\x3B\x8F_7\x87". "W3\x7FS\x2FwO\x2BkG\x27_C\x23S\x3F\x1FK7\x1B\x3F\x2F\x173\x2B\x13\x2B\x23\x0F\xEF\xEF\xEF". "\xE7\xE7\xE7\xDF\xDF\xDF\xDB\xDB\xDB\xD3\xD3\xD3\xCB\xCB\xCB\xC7\xC7\xC7\xBF\xBF\xBF\xB7\xB7\xB7\xB3\xB3\xB3\xAB\xAB\xAB\xA7\xA7". "\xA7\x9F\x9F\x9F\x0F\x17\x03\x17\x1F\x07O\x3B\x2B\x83\x83\x83\x23\x2B\x0Fwwwoookkkccc\x5B". "\x5B\x5BWWWOOOGGGCCC\x3B\x3B\x3B777\x17\x0F\x07\x27\x27\x27\x23\x23\x23w\xFFo". "o\xEFgg\xDF__\xCFW\x5B\xBFOS\xAFGK\x9F\x3FC\x937\x3F\x83\x2F7s\x2B\x2Fc\x23\x1F\x17". "\x0B\x1FC\x17\x173\x0F\x13\x23\x0B\x0B\x17\x07\x03\x03\x03\xB7\x9F\x87\xAF\x97\x7F\xA7\x8Fw\x9F\x87o\x9B\x7Fk\x93". "\x7Bc\x8Bs\x5B\x83kW\x7BcOw_KoWCgS\x3F_K7WC3S\x3F\x2F\x9F\x83c". "\x8FwS\x83kKw_\x3FgS3\x5BG\x2BO\x3B\x23C3\x1B\x7B\x7FcosWgkO\x5Bc". "GSW\x3BGO3\x3FG\x2B7\x3F\x27\xFF\xFFs\xEB\xDBW\xD7\xBBC\xC3\x9B\x2F\xAF\x7B\x1F\x9B\x5B\x13\x87". "C\x07s\x2B\x03\xFF\xFF\xFF\xFF\xDB\xDB\xFF\xBB\xBB\xFF\x9B\x9B\xFF\x7B\x7B\xFF__\xFF\x3F\x3F\xFF\x1F\x1F\xFF\x03\x03". "\xEF\x03\x03\x2F7\x1F\xFF\xFF\xFF\x7F\x7F\x7F\x07\x07\x07\x0B\x0B\x0B\x13\x13\x13\x1B\x1B\x1BKKK\x97\x97\x97\x93\x93". "\x93\x8B\x8B\x8B\x5B\x03\x03O\x03\x03\x27S\x1B\xE7\xE7\xFF\xC7\xC7\xFF\xAB\xAB\xFF\x8F\x8F\xFFss\xFFSS\xFF7". "7\xFF\x1B\x1B\xFF\x03\x03\xFF\x03\x03\xE3\x03\x03\xCB\x03\x03\xB3\x03\x03\x9B\x03\x03\x83\x03\x03k\x03\x03S\xFF\xFF\xFF". "\xFF\xEB\xDB\xFF\xD7\xBB\xFF\xC7\x9B\xFF\xB3\x7B\xFF\xA3\x5B\xFF\x8F\x3B\xFF\x7F\x1B\xF3s\x17\xEBo\x0F\xDFg\x0F\xD7_". "\x0B\xCBW\x07\xC3O\x03\xB7G\x03\xAFC\x03\xFF\xFF\xFF\xFF\xFF\xD7\xFF\xFF\xB3\xFF\xFF\x8F\xFF\xFFk\xFF\xFFG\xFF". "\xFF\x23\xFF\xFF\x03\xA7\x3F\x03\x9F7\x03\x93\x2F\x03\x87\x23\x03O\x3B\x27C\x2F\x1B7\x23\x13\x2F\x1B\x0B\x03\x03S". "\x03\x03G\x03\x03\x3B\x03\x03\x2F\x03\x03\x23\x03\x03\x17\x03\x03\x0B\xBF\xA7\x8F\xFF\x9FC\xFF\xE7K\xFF\x7B\xFF\xFF\x03". "\xFF\xCF\x03\xCF\x9F\x03\x9Bo\x03k\xA7kk\x21\xF9\x04\x01\x00\x00\x01\x00\x2C\x00\x00\x00\x00\x0E\x00\x10\x00\x00\x08". "\x93\x00\x03\x08\x0C\x00\xA0\xA0A\x83\x03\x0B\x12\x18\xA0\x60\x81\xC3\x01\x05\x00\x08\x20\x98\xC0\xC0\x01\x04\x08\x0E\x1C\x28". "\xC0\x80\x81D\x82\x06\x06\x0C\x20\x40\xB2\x24\x01\x89\x00\x08\x18P0\xE0\xE0A\x01\x00\x0A\x1C\x60\xE9R\x80M\x98". "\x05\x06\x2C\x60\xD8\x40\xE4\x81\x82\x02c\xEA\x1C\x80\xD1\xA2\xC5\x88\x04s6\x40P\x80\x24\x83\xA3\x28\x0B\x20\xE8y". "\xB0\x80\x81\x880\x13\x0C\xA0j\xD0\x2AV\x90\x3B\x15\x288\x60\x80\x40\x81\xAF\x00\x2A\x12E\xC0\x80d\x82\x93\x13". "\x09\xA6t\x9B\x20AA\x9B\x03a\xD6\xC4\x3BP\xE0\xCD\x9B\x03\x03\x02\x00\x3B"; $GifData[7]= "GIF89a\x0E\x00\x10\x00\xEF\x00\x00\x03\xFF\xFFC\x03\x03\x2F\x2F\x2F\x8B\x03\x03s\x03\x03\x9B\x03\x03\xB3". "\x03\x03\xA7\x03\x03\x7F\x03\x03\xBF\x03\x03g\x03\x03\x0F\x17\x03O\x3B\x2BG3\x23\x3F\x2B\x1B\x7F\x7F\x7F\xFF\xB7\xB7". "\xF7\xAB\xAB\xF3\xA3\xA3\xEB\x97\x97\xE7\x8F\x8F\xDF\x87\x87\xDB\x7B\x7B\xD3ss\xCBkk\xC7cc\xBF\x5B\x5B\xBBW". "W\xB3OO\xAFGG\xA7\x3F\x3F\xA3\x3B\x3B\x9B33\x97\x2F\x2F\x8F\x2B\x2B\x8B\x23\x23\x83\x1F\x1F\x7F\x1B\x1Bw". "\x17\x17s\x13\x13k\x0F\x0Fg\x0B\x0B_\x07\x07\x5B\x07\x07S\x07\x07O\x03\x03G\x03\x03C\x03\x03\xFF\xEB\xDF". "\xFF\xE3\xD3\xFF\xDB\xC7\xFF\xD3\xBB\xFF\xCF\xB3\xFF\xC7\xA7\xFF\xBF\x9B\xFF\xBB\x93\xFF\xB3\x83\xF7\xAB\x7B\xEF\xA3s\xE7\x9B". "k\xDF\x93c\xD7\x8B\x5B\xCF\x83S\xCB\x7FO\xBF\x7BK\xB3sG\xABoC\xA3k\x3F\x9Bc\x3B\x8F_7\x87". "W3\x7FS\x2FwO\x2BkG\x27_C\x23S\x3F\x1FK7\x1B\x3F\x2F\x173\x2B\x13\x2B\x23\x0F\xEF\xEF\xEF". "\xE7\xE7\xE7\xDF\xDF\xDF\xDB\xDB\xDB\xD3\xD3\xD3\xCB\xCB\xCB\xC7\xC7\xC7\xBF\xBF\xBF\xB7\xB7\xB7\xB3\xB3\xB3\xAB\xAB\xAB\xA7\xA7". "\xA7\x9F\x9F\x9F\x23\x2B\x0F\x2F7\x1F\x1B\x1B\x1B\x83\x83\x83\x17\x1F\x07wwwoookkkccc\x5B". "\x5B\x5BWWWOOOGGGCCC\x3B\x3B\x3B777KKK\x27\x27\x27\x23\x23\x23w\xFFo". "o\xEFgg\xDF__\xCFW\x5B\xBFOS\xAFGK\x9F\x3FC\x937\x3F\x83\x2F7s\x2B\x2Fc\x23\x17\x0F". "\x07\x1FC\x17\x173\x0F\x13\x23\x0B\x0B\x17\x07\x03\x03\x03\xB7\x9F\x87\xAF\x97\x7F\xA7\x8Fw\x9F\x87o\x9B\x7Fk\x93". "\x7Bc\x8Bs\x5B\x83kW\x7BcOw_KoWCgS\x3F_K7WC3S\x3F\x2F\x9F\x83c". "\x8FwS\x83kKw_\x3FgS3\x5BG\x2BO\x3B\x23C3\x1B\x7B\x7FcosWgkO\x5Bc". "GSW\x3BGO3\x3FG\x2B7\x3F\x27\xFF\xFFs\xEB\xDBW\xD7\xBBC\xC3\x9B\x2F\xAF\x7B\x1F\x9B\x5B\x13\x87". "C\x07s\x2B\x03\xFF\xFF\xFF\xFF\xDB\xDB\xFF\xBB\xBB\xFF\x9B\x9B\xFF\x7B\x7B\xFF__\xFF\x3F\x3F\xFF\x1F\x1F\xFF\x03\x03". "\xEF\x03\x03\xE3\x03\x03\xD7\x03\x03\xCB\x03\x03\x07\x07\x07\x0B\x0B\x0B\x13\x13\x13\xFF\xFF\xFF\x1F\x17\x0B\x97\x97\x97\x93\x93". "\x93\x8B\x8B\x8B\x5B\x03\x03O\x03\x03\x27S\x1B\xE7\xE7\xFF\xC7\xC7\xFF\xAB\xAB\xFF\x8F\x8F\xFFss\xFFSS\xFF7". "7\xFF\x1B\x1B\xFF\x03\x03\xFF\x03\x03\xE3\x03\x03\xCB\x03\x03\xB3\x03\x03\x9B\x03\x03\x83\x03\x03k\x03\x03S\xFF\xFF\xFF". "\xFF\xEB\xDB\xFF\xD7\xBB\xFF\xC7\x9B\xFF\xB3\x7B\xFF\xA3\x5B\xFF\x8F\x3B\xFF\x7F\x1B\xF3s\x17\xEBo\x0F\xDFg\x0F\xD7_". "\x0B\xCBW\x07\xC3O\x03\xB7G\x03\xAFC\x03\xFF\xFF\xFF\xFF\xFF\xD7\xFF\xFF\xB3\xFF\xFF\x8F\xFF\xFFk\xFF\xFFG\xFF". "\xFF\x23\xFF\xFF\x03\xA7\x3F\x03\x9F7\x03\x93\x2F\x03\x87\x23\x03O\x3B\x27C\x2F\x1B7\x23\x13\x2F\x1B\x0B\x03\x03S". "\x03\x03G\x03\x03\x3B\x03\x03\x2F\x03\x03\x23\x03\x03\x17\x03\x03\x0B\xBF\xA7\x8F\xFF\x9FC\xFF\xE7K\xFF\x7B\xFF\xFF\x03". "\xFF\xCF\x03\xCF\x9F\x03\x9Bo\x03k\xA7kk\x21\xF9\x04\x01\x00\x00\x00\x00\x2C\x00\x00\x00\x00\x0E\x00\x10\x00\x00\x08". "l\x00\x03\x08\x1C8\x10\x80A\x83\x01\x10\x14H\xC0\xF0\x40\x01\x02\x02\x0F\x06\x18P\xA0\xC0\x80\x03\x18\x0F\x0C\x80". "\x88\x90\x80\xC7\x8F\x04\x0CP\x0C\x20\x00\x00A\x82\x16\x0Dp\x04\x20\xA0\xA5\xCB\x00\x29\x0B\x90\x3CH\x13\xE6\x00\x91". "3i\x22\xD4\x88\xB3\xA4N\x93\x3Ce\xFA\xD49\xF1\xE6\x80\x9CD\x11\x18EZS\xC1M\x04L\x25\x3A5\x00". "uhM\x90Q\x11\x9E\xB4J\xD3\xA5\xCB\x80\x00\x3B"; $GifData[8]= "GIF89a\x0E\x00\x10\x00\xEF\x00\x00C\x03\x03\x03\xFF\xFF\x9B\x03\x03\x2F\x2F\x2F\x8B\x03\x03s\x03\x03g". "\x03\x03\xCB\x03\x03\xA7\x03\x03\xB3\x03\x03\xBF\x03\x03\xE3\x03\x03\x5B\x03\x03\xD7\x03\x03\x7F\x03\x03\xCBkk\xFF\xB7\xB7". "\xF7\xAB\xAB\xF3\xA3\xA3\xEB\x97\x97\xE7\x8F\x8F\xDF\x87\x87\xDB\x7B\x7BG3\x23\x3F\x2B\x1B\xC7cc\xBF\x5B\x5B\xBBW". "W\xB3OO\xAFGG\xA7\x3F\x3F\xA3\x3B\x3B\x9B33\xD3ss\x97\x2F\x2F\x8B\x23\x23\x83\x1F\x1F\x7F\x1B\x1Bw". "\x17\x17s\x13\x13k\x0F\x0Fg\x0B\x0B_\x07\x07\x5B\x07\x07S\x07\x07O\x03\x03G\x03\x03C\x03\x03\xFF\xEB\xDF". "\xFF\xE3\xD3\xFF\xDB\xC7\xFF\xD3\xBB\xFF\xCF\xB3\xFF\xC7\xA7\x8F\x2B\x2B\xFF\xBB\x93\xFF\xBF\x9B\xF7\xAB\x7B\xEF\xA3s\xE7\x9B". "k\xDF\x93c\xD7\x8B\x5B\xCF\x83S\xCB\x7FO\xBF\x7BK\xB3sG\xABoC\xA3k\x3F\x9Bc\x3B\x8F_7\x87". "W3\x7FS\x2FwO\x2BkG\x27_C\x23S\x3F\x1FK7\x1B\x3F\x2F\x173\x2B\x13\x2B\x23\x0F\xEF\xEF\xEF". "\xE7\xE7\xE7\xDF\xDF\xDF\xDB\xDB\xDB\xD3\xD3\xD3\xCB\xCB\xCB\xC7\xC7\xC7\xBF\xBF\xBF\xB7\xB7\xB7\xB3\xB3\xB3\xAB\xAB\xAB\xA7\xA7". "\xA7\x9F\x9F\x9F\x97\x97\x97\x0F\x17\x03\x17\x1F\x07\xFF\xB3\x83\x7F\x7F\x7Fwww\x83\x83\x83O\x3B\x2Bccc\x5B". "\x5B\x5BWWWOOOGGGCCC\x3B\x3B\x3B777\x23\x2B\x0F\x27\x27\x27\x23\x23\x23w\xFFo". "o\xEFgg\xDF__\xCFW\x5B\xBFOS\xAFGK\x9F\x3FC\x937\x3F\x83\x2F7s\x2B\x2Fc\x23\x2F7". "\x1F\x1FC\x17\x173\x0F\x13\x23\x0B\x0B\x17\x07\x03\x03\x03\xB7\x9F\x87\xAF\x97\x7F\xA7\x8Fw\x9F\x87o\x9B\x7Fk\x93". "\x7Bc\x8Bs\x5B\x83kW\x7BcOw_KoWCgS\x3F_K7WC3S\x3F\x2F\x9F\x83c". "\x8FwS\x83kKw_\x3FgS3\x5BG\x2BO\x3B\x23C3\x1B\x7B\x7FcosWgkO\x5Bc". "GSW\x3BGO3\x3FG\x2B7\x3F\x27\xFF\xFFs\xEB\xDBW\xD7\xBBC\xC3\x9B\x2F\xAF\x7B\x1F\x9B\x5B\x13\x87". "C\x07s\x2B\x03\xFF\xFF\xFF\xFF\xDB\xDB\xFF\xBB\xBB\xFF\x9B\x9B\xFF\x7B\x7B\xFF__\xFF\x3F\x3F\xFF\x1F\x1F\xFF\x03\x03". "\xEF\x03\x03\x07\x07\x07ooo\x0B\x0B\x0B\x13\x13\x13\x1B\x1B\x1B\xFF\xFF\xFFKKK\x17\x0F\x07kkk\x1F\x17". "\x0B\x93\x93\x93\x8B\x8B\x8BO\x03\x03\x27S\x1B\xE7\xE7\xFF\xC7\xC7\xFF\xAB\xAB\xFF\x8F\x8F\xFFss\xFFSS\xFF7". "7\xFF\x1B\x1B\xFF\x03\x03\xFF\x03\x03\xE3\x03\x03\xCB\x03\x03\xB3\x03\x03\x9B\x03\x03\x83\x03\x03k\x03\x03S\xFF\xFF\xFF". "\xFF\xEB\xDB\xFF\xD7\xBB\xFF\xC7\x9B\xFF\xB3\x7B\xFF\xA3\x5B\xFF\x8F\x3B\xFF\x7F\x1B\xF3s\x17\xEBo\x0F\xDFg\x0F\xD7_". "\x0B\xCBW\x07\xC3O\x03\xB7G\x03\xAFC\x03\xFF\xFF\xFF\xFF\xFF\xD7\xFF\xFF\xB3\xFF\xFF\x8F\xFF\xFFk\xFF\xFFG\xFF". "\xFF\x23\xFF\xFF\x03\xA7\x3F\x03\x9F7\x03\x93\x2F\x03\x87\x23\x03O\x3B\x27C\x2F\x1B7\x23\x13\x2F\x1B\x0B\x03\x03S". "\x03\x03G\x03\x03\x3B\x03\x03\x2F\x03\x03\x23\x03\x03\x17\x03\x03\x0B\xBF\xA7\x8F\xFF\x9FC\xFF\xE7K\xFF\x7B\xFF\xFF\x03". "\xFF\xCF\x03\xCF\x9F\x03\x9Bo\x03k\xA7kk\x21\xF9\x04\x01\x00\x00\x01\x00\x2C\x00\x00\x00\x00\x0E\x00\x10\x00\x00\x08". "\x95\x00\x03\x08\x04\x40\xB0\x20\x00\x81\x08\x010\x28\x20\x60\xC1\x82\x04\x02\x0A08\x18\x00\x80\x01\x02\x04\x04\x24P". "\x20\x40\x00F\x03\x07\x010\xCC\x98\xD1\x81\xC7\x88\x00\x06\x88\xF4x\xA0\xA0\x82\x8C\x05RZD\x40\xA0\x25\xC1\x03". "\x04\x10\x80\x1CP\xF1b\xC3\x06\x1C\x09\xEC\xE4Y1\x27\x82\xA34S\x12\xB5\x28\x00A\x81\xA7\x08\x04\x80\x1Ch". "\x40\xA3M\x00\x07\x0EH\x0D\x991\xC1\xD5\x03\x09\x12\x10\x90I\x00\xA2\x80\x03\x0B\x0E\x20P\x20VfU\x8Fl". "\x3BB\xDCY\xF1\xA9\xDD\xBBJ\x07\x1A48\x80\xA8\xC0\xBE\x80\x03\x0B\x0C\x08\x00\x3B"; $GifData[9]= "GIF89a\x0E\x00\x10\x00\xEF\x00\x00C\x03\x03\x03\xFF\xFF\x2F\x2F\x2F\xB3\x03\x03\x8B\x03\x03s\x03\x03\x9B". "\x03\x03\xBF\x03\x03g\x03\x03\xCB\x03\x03\xA7\x03\x03\xE3\x03\x03\x7F\x03\x03\xD7\x03\x03\xEF\x03\x03\x2F7\x1F\xFF\xB7\xB7". "\xF7\xAB\xAB\xF3\xA3\xA3\xEB\x97\x97\xE7\x8F\x8F\xDF\x87\x87\xDB\x7B\x7B\xD3ss\xCBkk\xC7cc\xBF\x5B\x5B\xBBW". "W\xB3OO\xAFGG\xA7\x3F\x3F\xA3\x3B\x3B\x9B33\x97\x2F\x2F\x8F\x2B\x2B\x8B\x23\x23\x83\x1F\x1F\x7F\x1B\x1Bw". "\x17\x17s\x13\x13k\x0F\x0Fg\x0B\x0B_\x07\x07\x5B\x07\x07S\x07\x07O\x03\x03G\x03\x03C\x03\x03\xFF\xEB\xDF". "\xFF\xE3\xD3\xFF\xDB\xC7\xFF\xD3\xBB\xFF\xCF\xB3\xFF\xC7\xA7\xFF\xBF\x9B\xFF\xBB\x93\xFF\xB3\x83\xF7\xAB\x7B\xEF\xA3s\xE7\x9B". "k\xDF\x93c\xD7\x8B\x5B\xCF\x83S\xCB\x7FO\xBF\x7BK\xB3sG\xABoC\xA3k\x3F\x9Bc\x3B\x8F_7\x87". "W3\x7FS\x2FwO\x2BkG\x27_C\x23S\x3F\x1FK7\x1B\x3F\x2F\x173\x2B\x13\x2B\x23\x0F\xEF\xEF\xEF". "\xE7\xE7\xE7\xDF\xDF\xDF\xDB\xDB\xDB\xD3\xD3\xD3\xCB\xCB\xCB\xC7\xC7\xC7\xBF\xBF\xBF\xB7\xB7\xB7\xB3\xB3\xB3\xAB\xAB\xAB\xA7\xA7". "\xA7\x9F\x9F\x9FG3\x23\x0F\x17\x03O\x3B\x2B\x3F\x2B\x1B\x7F\x7F\x7Fwwwoookkkccc\x5B". "\x5B\x5BWWWOOOGGGCCC\x3B\x3B\x3B777\xFF\xFF\xFF\x27\x27\x27\x23\x23\x23w\xFFo". "o\xEFgg\xDF__\xCFW\x5B\xBFOS\xAFGK\x9F\x3FC\x937\x3F\x83\x2F7s\x2B\x2Fc\x23KK". "K\x1FC\x17\x173\x0F\x13\x23\x0B\x0B\x17\x07\x03\x03\x03\xB7\x9F\x87\xAF\x97\x7F\xA7\x8Fw\x9F\x87o\x9B\x7Fk\x93". "\x7Bc\x8Bs\x5B\x83kW\x7BcOw_KoWCgS\x3F_K7WC3S\x3F\x2F\x9F\x83c". "\x8FwS\x83kKw_\x3FgS3\x5BG\x2BO\x3B\x23C3\x1B\x7B\x7FcosWgkO\x5Bc". "GSW\x3BGO3\x3FG\x2B7\x3F\x27\xFF\xFFs\xEB\xDBW\xD7\xBBC\xC3\x9B\x2F\xAF\x7B\x1F\x9B\x5B\x13\x87". "C\x07s\x2B\x03\xFF\xFF\xFF\xFF\xDB\xDB\xFF\xBB\xBB\xFF\x9B\x9B\xFF\x7B\x7B\xFF__\xFF\x3F\x3F\xFF\x1F\x1F\xFF\x03\x03". "\x23\x2B\x0F\x17\x1F\x07\x07\x07\x07\x13\x13\x13\x0B\x0B\x0B\x17\x0F\x07\x1B\x1B\x1B\x83\x83\x83\x1F\x17\x0B\x97\x97\x97\x93\x93". "\x93\x8B\x8B\x8B\x5B\x03\x03O\x03\x03\x27S\x1B\xE7\xE7\xFF\xC7\xC7\xFF\xAB\xAB\xFF\x8F\x8F\xFFss\xFFSS\xFF7". "7\xFF\x1B\x1B\xFF\x03\x03\xFF\x03\x03\xE3\x03\x03\xCB\x03\x03\xB3\x03\x03\x9B\x03\x03\x83\x03\x03k\x03\x03S\xFF\xFF\xFF". "\xFF\xEB\xDB\xFF\xD7\xBB\xFF\xC7\x9B\xFF\xB3\x7B\xFF\xA3\x5B\xFF\x8F\x3B\xFF\x7F\x1B\xF3s\x17\xEBo\x0F\xDFg\x0F\xD7_". "\x0B\xCBW\x07\xC3O\x03\xB7G\x03\xAFC\x03\xFF\xFF\xFF\xFF\xFF\xD7\xFF\xFF\xB3\xFF\xFF\x8F\xFF\xFFk\xFF\xFFG\xFF". "\xFF\x23\xFF\xFF\x03\xA7\x3F\x03\x9F7\x03\x93\x2F\x03\x87\x23\x03O\x3B\x27C\x2F\x1B7\x23\x13\x2F\x1B\x0B\x03\x03S". "\x03\x03G\x03\x03\x3B\x03\x03\x2F\x03\x03\x23\x03\x03\x17\x03\x03\x0B\xBF\xA7\x8F\xFF\x9FC\xFF\xE7K\xFF\x7B\xFF\xFF\x03". "\xFF\xCF\x03\xCF\x9F\x03\x9Bo\x03k\xA7kk\x21\xF9\x04\x01\x00\x00\x01\x00\x2C\x00\x00\x00\x00\x0E\x00\x10\x00\x00\x08". "\x8E\x00\x03\x08\x0C\x00\xA0\x60\xC1\x81\x08\x0B\x2AH\x90\xE0\x40\x81\x83\x03\x01\x10P\x60\x40\xC1\x80\x01\x14\x11\x00\x10". "\x08\x00\xC1D\x03\x0C\x0A\x14\x18p\xC0\x00\x00\x01\x04\x0D\x10Pip\x40\x02\x03\x0FS\xAE\x24\xD02\x81\x02\x9A". "\x02\x3A\x12\xD89\x60A\xC3\x06\x07p\x12\x2C\xE0\xF1\x22I\xA0B\x09vDP\x80\x00\x83\x05AO\x0E\xCCi". "\xF0\xE9\x00\x9C\x06\xB3\x02xz\x40cN\x97\x0D\x168\x60x\xA0\x81I\x019\x0D\x185Z\xD2\xEBP\x91p". "E\x16D\xABT\xEB\x5C\xBA\x02\xD1\xEA\xDD\x8B0\x20\x00\x3B"; ###################################################### sub Number2gif{ my($Number,$digits)=@_; my($Ascii_Num,$Zeropad,$n_gif,$Gif_Answer,$logsrc,$pal); my($gif_log_scr_packed,$gif_transps,$gif_img_desc,$gif_dat,$packed_was); $Gif_Answer="$gifheader"; #GIF89a $logsrc=pack('S2C3',$digx_size*$digits,$digy_size,pack('B8','01100000'),0,0); $Gif_Answer .=$logsrc; $Ascii_Num=''.$Number; $digits=($digits>length($Ascii_Num)?$digits:length($Ascii_Num)); $Zeropad='0' x $digits; substr($Zeropad,- length($Ascii_Num),length($Ascii_Num))=$Ascii_Num; $Ascii_Num=$Zeropad; foreach(0..length($Ascii_Num)-1){ $n_gif=0+substr($Ascii_Num,$_,1); $pal=substr($GifData[$n_gif],13,256*3); $gif_log_scr_packed=unpack('B8',substr($GifData[$n_gif],10,1)); $gif_transps=substr($GifData[$n_gif],13+256*3,8); $gif_img_desc=substr($GifData[$n_gif],13+256*3+8,10); $gif_dat=substr($GifData[$n_gif],13+256*3+8+10,length($GifData[$n_gif])); $gif_dat=substr($gif_dat,0,length($gif_dat)-1); substr($gif_img_desc,1,2)=pack('S',$_*$digx_size); $packed_was=unpack('B8',substr($gif_img_desc,9,1)); substr($gif_img_desc,9,1)=pack('B8','1'. substr($packed_was,1,1). substr($gif_log_scr_packed,4,1).'00'.substr($gif_log_scr_packed,5,3)); $Gif_Answer.=$gif_transps.$gif_img_desc.$pal.$gif_dat; } $Gif_Answer.='\x3B'; return $Gif_Answer; } ###################################################### sub urldecode{ local($val)=@_; $val=~s/\+/ /g; $val=~s/%([0-9A-H]{2})/pack('C',hex($1))/ge; return $val; } sub debug_err{ open DEBUGFILE,">>debug.txt"; print DEBUGFILE $ENV{'SCRIPT_NAME'}.' '.scalar(localtime).' '.@_."\n"; close DEBUGFILE; } $query=$ENV{'QUERY_STRING'}; if($query eq ''){print "Content-Type: image/gif\n\n$GifData[0]";} else{ @fields=split /&/,$query; foreach(@fields){ if(/^id=(.*)/){$id=urldecode($1);} if(/^dig=(.*)/){$dig=urldecode($1);} } $digits=$dig; $digits=9 unless($dig); $cur_ip=$ENV{'REMOTE_ADDR'}; $cur_time=time; open DATA,"+<$datafile" || debug_err("Cannot open $datafile $!"); @Dat=<DATA>; chomp(@Dat); %Counters=@Dat; ($count,$ip,$t)=split /\s+/,$Counters{$id}; $count++ if(($ip!=$cur_ip)||($cur_time-$t>30)); $ip=$cur_ip; $t=$cur_time; $Counters{$id}=join ' ',$count,$ip,$t; seek DATA,0,0; foreach(keys %Counters){ print DATA "$_\n"; print DATA "$Counters{$_}\n"; } truncate(DATA,tell(DATA)); close DATA; print "Content-Type: image/gif\n\n"; print Number2gif($count,$digits); }

Если вам циферки не понравились вы их легко сможете заменить.Новые .gif'ы либо считайте из файла, либо можете продолжить мою традицию и запихнуть их в строку, в чем вам поможет такой скрипт file2str. (Да и еще не забудьте сменить тогда в скрипте константы $digx_size и $digy_size на новый размер цифр.)



#!/usr/bin/perl #file2str unless(@ARGV){die "Usage: file2str file strfile\n";} open F1,"$ARGV[0]" || die "Cannot open $ARGV[0] $!\n"; open F2,">$ARGV[1]" || die "Cannot open $ARGV[1] $!\n"; binmode(F1); sysread F1,$filedata,-s F1; close(F1); for($i=0;$i<=length($filedata)/32;$i++){ $data=substr($filedata,$i*32,32); $data=~s/(\W)/sprintf("\\x%02X",unpack('C',$1))/eg; print F2 "\"$data\".(length($data)==32?".":";")."\n";" } close(F2);


Ssi


Теперь посмотрите, что вы натворили. Мда, натворили. Допустим, вы уже сделали сайт. К примеру, на нем 30 страниц с общим дизайном, причем на каждой странице есть навигация, например, по разделу. Что произойдет, если вы добавите в раздел новую статью? Правильно, вам понадобится изменять все страницы, входящие в раздел. Хорошо если их 10. А если больше? А если вам необходимо дизайн поменять?

Мда, ситуация незавидная. С такой ситуацией я столкнулся, когда пытался сделать похожий ресурс на бесплатном сервере. Это кончилось тем, что я просто не смог обновлять сайт. К счастью, есть выход! Этим выходом является технология Server-Side Includes (включения на стороне сервера), в просторечии SSI. Она, если сервер ее поддерживает, позволяет прямо-таки творить чудеса. Суть в следующем - включив в свою страничку код

<!--#include virtual="header.ssi" -->

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

<!--#exec cgi="cgi.pl" -->

Вот так. После этого вы можете переделать свои страницы так, что смену дизайна можно будет произвести за 5 минут, изменив только два-три файла. Именно это я могу сделать со своим сервером. В моем случае страница, которую вы видите как чистый HTML, на самом деле состоит из заголовка с META-тэгами, особыми для каждой страницы, заголовка страницы, потом идет общий заголовок (SSI), потом подзаголовок в темно-серой линии, потом навигация по разделу (SSI), потом текст, потом "стопа" документа (SSI). Вот так:

<html>

<head>

<meta http-equiv="Content-Language" content="ru">

<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">

<title>Кормушка :: Локальная копия :: HTML учебник</title>

<!--#include virtual="header.ssi" -->

<p><b><a href="index.shtml">Кормушка</a>

 :: <a href="local.shtml">Локальная копия</a>

 :: HTML учебник</b>

</p>

<!--#include virtual="leftnav.ssi" -->

<!--#include virtual="localheader.ssi" -->

Тут лежит текст

<!--#include virtual="rightnav.ssi" -->

</body>

</html>

Как видите, все гениальное просто. Попробуйте аналогичные преобразования на своих страницах. Не получилось? Еще бы! Это же Server-Side Includes. Для просмотра SSI-документов на своей машине необходимо установить сервер. О том, как это сделать, читайте в следующей статье.

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


<!--#include file="file.html" --> или



<!--#include virtual="URL" -->



Первый случай используется при подключении файла, находящегося в том же самом каталоге, второй – для подключения файла, находящегося в любом месте, даже на другом сервере. (Но не все бесплатные сервера разрешат вам подключить файл, находящийся на другом сервере). Все говорят, что предпочтительнее использовать virtual, и я не буду спорить. В этом случае можно использовать как относительные, так и абсолютные адреса. Само собой разумеется, что подключаемый файл тоже, в свою очередь, может содержать директивы SSI. Обратите внимание: пробелы есть только после слова include и перед -->. Желательно, чтобы файл, в котором есть директивы SSI, имел вид name.shtml, где name – любая комбинация латинских букв, цифр и знаков подчеркивания. На некоторых серверах разрешают вставлять директивы SSI и в файлы с расширением *.htm, *.html.

Данные

Для хранения данных существуют переменные. Они объявляются так:



<!--#set var="имя" value="значение" -->



Передача данных

Передавать данные можно двумя способами. Даже тремя.

Используя метод get формы.

Через URL вызываемого файла в виде
file.html?param=value[&param=value].

Используя возможности SSI.

В принципе, первые два различаются лишь тем, самостоятельно будете вы кодировать строку запроса (2-й способ) или предоставите это делать пользователю (1-й способ), который будет заполнять форму и жать на ОК или SUBMIT. Этот способ рассмотрен мною подробно в другой статье. Для передачи данных средствами SSI достаточно объявить переменную и присвоить ей значение. Теперь она доступна из любого файла, подключающего данный.

Получение данных

Получить и затем использовать данные можно двумя способами.

Стандартными средствами DHTML (HTML+JavaScript)

Средствами SSI.

Первый способ рассмотрен все в той же статье "Передача данных…", да и не интересует он нас сейчас. А вот средствами SSI получить данные можно опять-таки двумя способами.



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

Если вы самостоятельно сформировали строку запроса так, как описано выше, или передавали данные из формы, это равносильно объявлению переменных. То есть строка file.shtml?param=value эквивалентна объявлению переменной param, равной value.

<!--#set var="param" value="value" -->

Чтобы проверить, передались ли вам какие-либо данные или нет, есть директива

<!--#printenv -->

Она выводит на экран список всех переменных и их значения.

Обработка данных

Нет смысла передавать данные и не использовать их потом. Разве что делать это с целью заморочить голову посетителю. Самое простое, что можно сделать, это вставить переменную в текст документа.



<!--#echo var="$name" --> -

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



<a href="<!--#echo var="$url" -->">

Ссылка</a>.



Или, например, посетитель сказал нам, как его зовут, нажал на кнопочку, и на следующей странице к нему будем обращаться по имени. Строка запроса у нас получилась
file.shtml?name=Alexey и используем мы эти бесценные сведения



Привет,

<!--#echo var="$name" -->.



В результате на экране отобразится Привет, Alexey.

Если передавались данные, требующие аналитической обработки, на это есть директива if.

<!--#if expr=(условие) -->

<!--#elif expr=(условие) -->



<!--#else -->

<!--#endif -->

endif является обязательным элементом. elif может повторяться сколько угодно раз. else между if и endif может быть лишь единожды, причем после else уже не может использоваться elif. После каждого условия можете вставлять неограниченное количество строчек кода HTML. Например, предыдущий пример (с именем) можно модернизировать





<!--#if expr=($name="Alexey") -->

<h1>Привет, <!--#echo var="$name" --></h1>

<!--#else -->

<h2>Привет, <!--#echo var="$name" --></h2>

<!--#endif -->



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

Организация сайта

Наконец-то я добрался до того, ради чего и затеял-то писать эту статью. Мы же хотим организовать свой сайт так, чтобы в случае чего модернизация заняла бы минимум усилий. Возможны два пути для достижения этой цели. Видите, какой я нынче демократичный – всегда предоставляю вам право выбора. Цените это J

. Следует учесть, что HTML – очень терпимый к ошибкам язык. Если вы что-то неправильно написали, к фатальным последствиям это не приведет. Так, например, не смотря на то, что во всех руководствах заголовок документа (head) рекомендуют писать в начале файла, броузеры правильно понимают его в любой части документа, даже если вы забудете заключить его в контейнер <head>. Единственное (имхо) неудобство заключается в том, что, располагая заголовок, содержащий title, в конце файла, страница броузера остается безымянной до тех пор, пока не прочитает этот заголовок.

Способ первый

Пишем статью в формате HTML, как обычно, но не указывая никакие стили, избегая изменения цветов (потому что мало ли какой цвет фона нам потом приспичит сделать – вдруг видно не будет) и даже опуская тег body. Остаются только font size, b, big, img, a, i, table и некоторые другие. Сохраняем как filename.html. Имя, естественно, у каждой статьи разное. Самое главное – запомнить, в каком файле какая статья лежит, а лучше записывать это. Адрес этой статьи никому не говорим – он для сугубо внутреннего использования.

Далее создаем публичный файл статьи. В начале документа пишем <html> и затем объявляем переменные, в которых будем передавать информацию о статье



<html>

<!--#set var="description" value="описание" -->



<!--#set var="title" value="Заголовок" -->

<!--#set var="keywords" value="ключевые слова" -->

<!--#set var="file" value="url статьи" -->

<!--#include virtual="файл интерфейса.shtml" -->



Сохраняем это все и запоминаем адрес – это и будет адрес статьи, который вы будете регистрировать в каталогах и рекомендовать посетить друзьям. Можно еще написать то, что вы там еще обычно пишете в заголовке. Я чаще всего ограничиваюсь одним title. Как-то спокойно отношусь к тому, что релевантность маленькая окажется J

.

Теперь создаем файл интерфейса (*,shtml). Начало его выглядит так:



<html><head>

<title><!--#echo var="$title" --></title>

<meta name="description" content="<!--#echo var="$description" -->">

<meta name="keywords" content="<!--#echo var="$keywords" -->">

</head>



Далее оформляем внешний вид – вешаем баннеры, вставляем счетчики, добавляем новости и т.д. Наконец в том уголке, где должна быть статья, пишем



<!--#include virtual="$file" -->



Все. Теперь, как и обещалось, для радикального изменения дизайна достаточно изменить лишь наш файл интерфейса.

Способ второй

Честно говоря, он мне не очень нравится, и поэтому я его приводить не буду. Идея его заключается в том, чтобы вызывать все статьи как, например, index.shtml?sub=filename. Выигрыш можно получить в том, что одна и та же статья теперь имеет два адреса. Кому интересно, можете сами организовать такую структуру.

Заключение

Некоторые тонкости. Обращение к переменным я делал как "$name". На сервере, где мой хоумпейдж, работает именно так. На других может быть "${name}" (скорее всего) или как-нибудь по-другому (маловероятно).

При тестировании дома могут возникнуть сложности. Для получения данных нужен сервер. Если у вас не стоит Apache или какой-нибудь другой и вы не хотите его ставить, и не надо. Есть хорошая программка Small HTTP Server (около 60кб). Последний раз я видел ее по адресу http://wwwkoi.wplus.net/pp/mrdoors/srv/rdesc.htm. После установки вы сможете тестировать дома CGI, SSI, PHP и т.д.

Статья взята с сайта Bookware.Ru. Автор - Алексей Годовник.


Ссылки на найденный текст


Иногда нужно сослаться на подстроку текста, для которой получено совпадение с некоторой частью шаблона. Например, при обработке файла, HTML может потребоваться выделять фрагменты текста, ограниченные открывающими и закрывающими метками HTML (например, <А> и </А>). В начале уже приводился пример, в котором выделялся текст, ограниченнуй метками HTML <А> и <B>. Следующий пример позволяет выделять текст, расположенный между любыми правильно закрытыми метками:

$text = "<А>Here is an anct1or.</А>"; if($text=~m%<([A-Za-z]+)>[\w\s\.]+</\1>%i){ }

Вместо косой черты в качестве ограничителя шаблона использован другой символ. Это позволяет использовать символ косой черты внутри шаблона без предшествующей ему обратной косой черты. Каждому фрагменту шаблона, заключенному в круглые скобки, соответствует определенная внутренняя переменная. Переменные пронумерованы, так что на них можно ссылаться внутри шаблона, поставив перед номером обратную косую черту (\1, \2, \3,...). На значения переменных можно ссылаться внутри шаблона, как на обычный текст, поэтому </\1> соответствует </\A>, если открываю-щей меткой служит, и , если открывающей меткой служит .

Эти же самые внутренние переменные можно использовать и вне шаблона, ссылаясь на них как на скаляры с именами $1, $2, $3,..., $n: $text = "I have 4 apples."; if ($text =- /(\(\d+)/) { print "Here Is the number of apples: $1.\n"; Here is the number of apples: 4.

Каждой паре скобок внутри шаблона после завершения операции поиска будет соответствовать скалярная переменная с соответствующим номером. Это можно 'использовать при выделении нужных для последующей работы фрагментов ана-лизируемой строки. В следующем примере мы изменяем порядок трех слов в тек-стовой строке с помощью команды s/.../.../:

$text = "I see you."; $text=-s/^(\w+) *(\w+) *(\w+)/$3 $2 $1/; print $text; you see I.

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

$text = "ABCDEFGH"; $text =- m/(\w(\w)(\w))((\w)(\w))/; print "$1/$2/$3/$4/$5/$6/"; ABC/B/C/DE/D/E

Кроме переменных, ссылающихся на найденный текст, можно использовать специальные переменные perl.



Trics and traps


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

Я вам в этой части расскажу о всяких тонких и неочевидных местах и о том как с этим боротся.

Продолжая тему отладки, я столкнулся с такой неочевидной проблеммой, помимо того,что надо перевести раскладку Windows (или DOS) в koi8-r

На некоторых серверах (в том числе на нашем UIC'овском) скрипт все равно отказывался работать. Признаюсь ,хоть и разобрался в чем дело я быстро, причина весьма неочевидна: Дело в том,что текстовый файл Windows содержит перед символом перехода на новую строку еще символ возврата каретки. А вот из-за этого скрипт и отказывался выполнятся, что содержал этот символ!

Методом решения (этот процесс как и все я максимально автоматизирую) стал коротенький скрипт delcr .Просто "натравливайте" его на ваши скрипты:delcr *.cgi

#!/usr/bin/perl #delcr unless(@ARGV){die "Usage: delcr file ....\n";} foreach $file(@ARGV){ if(! -r $file || ! -w $file){print "$file: access denied\n";} else{ open F,"+<$file"|| die "Cannot open $file $!\n"; binmode F || die "Cannot binmode $file $!\n"; @D=<F>; seek F,0,0; foreach(@D){ s/\r//g; print F; } truncate F,tell(F); close F; } }

Саму же взаимную перекодировку Dos<->koi-8<->Win поможет выполнить вот такая прога. Написал я ее очень давно, даже раньше чем занялся CGI программированием и с тех давних пор она меня все время выручала, став моим по-настоящему незаменимым и верным другом. Итак, знакомьтесь: txtconv -Утилита перевода раскладок символов.

#include<stdio.h> #include<string.h> /*****************/ char tbldw[256]={ 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f, 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f, 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f, 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f, 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,


0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf, 0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf, 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef, 0x5f,0x5f,0x5f,0xa6,0xa6,0xa6,0xa6,0x2b,0x2b,0xa6,0xa6,0x2b,0x2b,0x2b,0x2b,0x2b, 0x2b,0x2d,0x2d,0x2b,0x2d,0x2b,0xa6,0xa6,0x2b,0x2b,0x2d,0x2d,0xa6,0x2d,0x2b,0x2d, 0x2d,0x2d,0x2d,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x5f,0x5f,0x5f,0x5f,0x5f, 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff, 0xa8,0xb8,0xaa,0xba,0xaf,0xbf,0xa1,0xa2,0xb0,0x95,0xb7,0x5f,0xb9,0xa4,0x5f,0x5f }; char tblwd[256]={ 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f, 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f, 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f, 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f, 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,

0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f, 0x5f,0x5f,0x5f,0x5f,0x5f,0xf9,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f, 0x5f,0xf6,0xf7,0x5f,0xfd,0x5f,0x7c,0x15,0xf0,0x63,0xf2,0x11,0x2d,0x2d,0x72,0xf4, 0xf8,0x5f,0x49,0x69,0x5f,0x5f,0x14,0xfa,0xf1,0xfc,0xf3,0x10,0x5f,0x5f,0x5f,0xf5, 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f, 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f, 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf, 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef }; char tbl_asc[256]={ 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f, 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f, 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f, 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f, 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f }; char tbldu[256]={ 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f, 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f, 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f, 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f, 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,



0xE1,0xE2,0xF7,0xE7,0xE4,0xE5,0xF6,0xFA,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0, 0xF2,0xF3,0xF4,0xF5,0xE6,0xE8,0xE3,0xFE,0xFB,0xFD,0xFF,0xF9,0xF8,0xFC,0xE0,0xF1, 0xC1,0xC2,0xD7,0xC7,0xC4,0xC5,0xD6,0xDA,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0, 0x90,0x91,0x92,0x81,0x87,0xB2,0xB4,0xA7,0xA6,0xB5,0xA1,0xA8,0xAE,0xAD,0xAC,0x83, 0x84,0x89,0x88,0x86,0x80,0x8A,0xAF,0xB0,0xAB,0xA5,0xBB,0xB8,0xB1,0xA0,0xBE,0xB9, 0xBA,0xB6,0xB7,0xAA,0xA9,0xA2,0xA4,0xBD,0xBC,0x85,0x82,0x8D,0x8C,0x8E,0x8F,0x8B, 0xD2,0xD3,0xD4,0xD5,0xC6,0xC8,0xC3,0xDE,0xDB,0xDD,0xDF,0xD9,0xD8,0xDC,0xC0,0xD1, 0xB3,0xA3,0x99,0x98,0x93,0x9B,0x9F,0x97,0x9C,0x95,0x9E,0x96,0xBF,0x9D,0x94,0x9A }; char tblud[256]={ 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f, 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f, 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f, 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f, 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,

0xC4,0xB3,0xDA,0xBF,0xC0,0xD9,0xC3,0xB4,0xC2,0xC1,0xC5,0xDF,0xDC,0xDB,0xDD,0xDE, 0xB0,0xB1,0xB2,0xF4,0xFE,0xF9,0xFB,0xF7,0xF3,0xF2,0xFF,0xF5,0xF8,0xFD,0xFA,0xF6, 0xCD,0xBA,0xD5,0xF1,0xD6,0xC9,0xB8,0xB7,0xBB,0xD4,0xD3,0xC8,0xBE,0xBD,0xBC,0xC6, 0xC7,0xCC,0xB5,0xF0,0xB6,0xB9,0xD1,0xD2,0xCB,0xCF,0xD0,0xCA,0xD8,0xD7,0xCE,0xFC, 0xEE,0xA0,0xA1,0xE6,0xA4,0xA5,0xE4,0xA3,0xE5,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE, 0xAF,0xEF,0xE0,0xE1,0xE2,0xE3,0xA6,0xA2,0xEC,0xEB,0xA7,0xE8,0xED,0xE9,0xE7,0xEA, 0x9E,0x80,0x81,0x96,0x84,0x85,0x94,0x83,0x95,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E, 0x8F,0x9F,0x90,0x91,0x92,0x93,0x86,0x82,0x9C,0x9B,0x87,0x98,0x9D,0x99,0x97,0x9A }; char tbluw[256]={ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F, 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F, 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F, 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F, 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F, 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F, 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,



0x2D,0xA6,0x2B,0x2B,0x2B,0x2B,0x2B,0xA6,0x2D,0x2D,0x2B,0x5F,0x5F,0x5F,0x5F,0x5F, 0x5F,0x5F,0x5F,0xAF,0x5F,0x95,0x5F,0xA2,0xBA,0xAA,0x5F,0xBF,0xB0,0xA4,0xB7,0xA1, 0x2D,0xA6,0x2B,0xB8,0x2B,0x2B,0x2B,0x2B,0x2B,0x2B,0x2B,0x2B,0x2B,0x2B,0x2B,0xA6, 0xA6,0xA6,0xA6,0xA8,0xA6,0xA6,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2B,0x2B,0x2B,0xB9, 0xFE,0xE0,0xE1,0xF6,0xE4,0xE5,0xF4,0xE3,0xF5,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE, 0xEF,0xFF,0xF0,0xF1,0xF2,0xF3,0xE6,0xE2,0xFC,0xFB,0xE7,0xF8,0xFD,0xF9,0xF7,0xFA, 0xDE,0xC0,0xC1,0xD6,0xC4,0xC5,0xD4,0xC3,0xD5,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE, 0xCF,0xDF,0xD0,0xD1,0xD2,0xD3,0xC6,0xC2,0xDC,0xDB,0xC7,0xD8,0xDD,0xD9,0xD7,0xDA }; char tblwu[256]={ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F, 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F, 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F, 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F, 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F, 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F, 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,

0x5F,0x5F,0x5F,0x5F,0x5F,0x5F,0x5F,0x5F,0x5F,0x5F,0x5F,0x5F,0x5F,0x5F,0x5F,0x5F, 0x5F,0x5F,0x5F,0x5F,0x5F,0x95,0x5F,0x5F,0x5F,0x5F,0x5F,0x5F,0x5F,0x5F,0x5F,0x5F, 0x5F,0x9F,0x97,0x5F,0x9D,0x5F,0x7C,0x15,0xB3,0x63,0x99,0x11,0x2D,0x2D,0x72,0x93, 0x9C,0x5F,0x49,0x69,0x5F,0x5F,0x14,0x9E,0xA3,0xBF,0x98,0x10,0x5F,0x5F,0x5F,0x9B, 0xE1,0xE2,0xF7,0xE7,0xE4,0xE5,0xF6,0xFA,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0, 0xF2,0xF3,0xF4,0xF5,0xE6,0xE8,0xE3,0xFE,0xFB,0xFD,0xFF,0xF9,0xF8,0xFC,0xE0,0xF1, 0xC1,0xC2,0xD7,0xC7,0xC4,0xC5,0xD6,0xDA,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0, 0xD2,0xD3,0xD4,0xD5,0xC6,0xC8,0xC3,0xDE,0xDB,0xDD,0xDF,0xD9,0xD8,0xDC,0xC0,0xD1 }; /*****************/ int convert(unsigned char *buff,unsigned char *Tbl,int count) { int i; for(i=0;i<count;i++)buff[i]=Tbl[(unsigned)buff[i]]; return 0; } /*****************/ char szHelp[]= "Text file converter (c)lesha 1998\n" "Usage:txtconv <options> <srcfile> <dstfile>\n" " options: -ud koi8->dos\n" " -du dos->koi8\n" " -uw koi8->win\n" " -wu win->koi8\n" " -dw dos->win\n" " -wd win->dos\n" " -? -This help\n"; int main(int argc,char *argv[]) { FILE *f1; FILE *f2; char tmpbuff[1024]; char *xtbl=NULL; int nr; if((argc>1)&&(strcmp(argv[1],"-?")==0)){printf(szHelp);return 0;} if(argc<4){printf(szHelp);return 0;} if (strcmp(argv[1],"-ud")==0)xtbl=tblud; else if(strcmp(argv[1],"-du")==0)xtbl=tbldu; else if(strcmp(argv[1],"-uw")==0)xtbl=tbluw; else if(strcmp(argv[1],"-wu")==0)xtbl=tblwu; else if(strcmp(argv[1],"-dw")==0)xtbl=tbldw; else if(strcmp(argv[1],"-wd")==0)xtbl=tblwd; if(xtbl==NULL){printf("unknown option:%s",argv[1]);return 1;} if((f1=fopen(argv[2],"rb"))==NULL){perror(argv[2]);return 1;} if((f2=fopen(argv[3],"wb"))==NULL){fclose(f1);perror(argv[3]);return 1;} while((nr=fread(tmpbuff,1,sizeof(tmpbuff),f1))>0) { convert(tmpbuff,xtbl,nr); fwrite(tmpbuff,1,nr,f2); } fclose(f1); fclose(f2); return 0; }

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

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

Желаю вам удачи. А пока посмотрите на некоторые примеры приложений, возможно они вам будут полезны.


"...Upload everything in cgi-bin in ASCII mode to a directory on your server that can run cgi..."


Теперь надо создать на сервере необходимые директории и загрузить туда файлы - четко следуйте инструкциям! Загружать надо в ASCII режиме! Что это? Есть два режима: ASCII и Binary - обычно для закачки/перекачки используется второй, но со *.cgi, *.pl файлами это не пройдет: 500 Server Errors - эта ошибка чаще всего появляется из-за неправильного режима загрузки! Выбор режима загрузки производится с помощью вашего ftp клиента (у меня Сutftp, скачать можно здесь: http://www.cuteftp.com/products/cuteftp/) - есть там нечто вроде Transfer Type - это оно самое, часто стоит на автомате (Auto), но иногда выбирает не тот режим (убедился лично) - лучше поставьте ASCII и не мучайтесь!



Установка CGI скриптов - не вляпайся!


Прислал: Green Kakadu [ 07.01.2001 @ 12:47 ]
Раздел:: [ Статьи по Perl ]


Эту статью я написал, т.к. почувствовал необходимость в этом: сам я с cgi скриптами намучался, и многие читатели меня спрашивали. Скажу сразу, что я вовсе не профессионал (как думают некоторые мои читатели), а простой Вася Пупкин, который вознамерился покорить Интернет. После некоторых потуг, у меня что-то стало получаться (далеко не все!), я заметил, что с проблемой "первого знакомства" со скриптами (и не только cgi) постоянно сталкивается множество людей - меня постоянно просят "помочь со скриптами" … И вот я решил изложить основные моменты по их установке, ничего особенного здесь нет, все это вы сможете найти и в инструкции, прилагаемой к каждому скрипту, но я попытался написать это нормальным человеческим языком...

Когда я сказал, что я не профи, то соврал! Есть у меня одно умение, в котором я признанный профессионал - это совершать все возможные и самые наиглупейшие ошибки!!! Поковыпявшись в CGI скриптах всего три недельки, я умудрился совершить почти все ошибки при их усановке: все что можно сделать неправильно - я сделал! Поэтому, чтоб уберечь вас от неверных действий, я изложу вам основные моменты по установке CGI скриптов. Не пугайтесь, это не так сложно как кажется - даже у меня что-то получилось, а я сам услышал о них недавно! Приступим....



Установка cookie.


Как выставлять cookies клиенту зависит от того, как они будут

использоваться в дальнейшем. Это можно делать как с помощью скриптов,

так и с помощью META-тагов HTML. Можно манипулировать временем

жизни выставленных cookies и устанавливать место, в котором установки

действительны. Общий формат установки таков:

Set-Cookie: NAME=value; EXPIRES=date; DOMAIN=domain_name; PATH=path; SECURE

Более подробно об этом можно прочитать в статье "Формат и синтаксис Cookies"



Установка cookie с использованием Perl/CGI.


Другой способ выставить cookie - с помощью серверного скрипта.

На Perl это будет выглядеть примерно следующим образом: перед

тем как выдавать серверный ответ генерируется HTTP заголовок

print "Content-type: text/html\n";

print "Set-Cookie: username=aaa13; expires=Friday,31-Dec-99 23:59:59 GMT; path=/win/internet/html/; domain=citforum.ru;\n\n";

Чтобы прочитать скриптом значение cookie, которое было установлено

ранее, и соответствующим образом выполнить скрипт, используется

переменная окружения HTTP_COOKIE. На Perl это будет выглядеть

так:

$cookie = $ENV{'HTTP_COOKIE'};

При использовании SSI для просмотра значения cookie можно применить

директиву:

<!--#echo var="HTTP_COOKIE"-->



Установка cookie с помощью HTML.


Простейший способ выставить cookie - использовать соответствующий

META-таг в заголовке <HEAD> </HEAD> любого статического

HTML документа. Это выглядит следующим образом:

<META HTTP-EQUIV="Set-Cookie" CONTENT="NAME=value; EXPIRES=date; DOMAIN=domain_name; PATH=path; SECURE">



Установка нескольких cookie одновременно.


Как с помощью HTML, так и с помощью скриптов можно устанавливать

несколько cookie разом:

HTML:

<META HTTP-EQUIV="Set-Cookie" CONTENT="NAME=value; EXPIRES=date; DOMAIN=domain_name; PATH=path; SECURE">

<META HTTP-EQUIV="Set-Cookie" CONTENT="NAME=value; EXPIRES=date; DOMAIN=domain_name; PATH=path; SECURE">

Perl/CGI:

print "Content-type: text/html\n";

print "Set-Cookie: NAME=value; EXPIRES=date; PATH=path; DOMAIN=domain_name; SECURE\n";

print "Set-Cookie: NAME=value; EXPIRES=date; PATH=path; DOMAIN=domain_name; SECURE\n\n";



Встроенные хеши


Переменные окружения, использующие встроенные хэши %SIG, %ENV, %FORM{}.

%SIG - хэш, в котором хранятся обработчики различных

ситуаций, возникающих в perl. Например строка local $SIG{__WARN__} = sub{}; отключает предупреждающие сообщения.

%ENV содержит значения переменных среды(окружения), заданных на момент запуска сценария(скрипта).

Ключами обычно бывают имена переменных среды(но их состав зависит от операционной системы), изменение этих значений

вызовет изменение окружения для процессов потомков.

#!/usr/bin/perl/ -w

while (($key, $value) = each(%ENV)){

print "$key => $value\n";

}

программа выдает:

SERVER_SOFTWARE => Apache/1.3.11 (FreeBSD) mod_perl/1.21 PHP/3.0.14

GATEWAY_INTERFACE => CGI/1.1

DOCUMENT_ROOT => /usr/local/www/data

UNIQUE_ID => OZaSFsHofQoAAEd@Cn8

REMOTE_ADDR => 195.202.122.14

SERVER_PROTOCOL => HTTP/1.0

SERVER_SIGNATURE => Apache/1.3.11 Server at www.mojdodir.ru Port 80

REQUEST_METHOD => GET

REMOTE_HOST => www.mojdodir.ru

QUERY_STRING =>

HTTP_USER_AGENT => Mozilla/4.73 [en] (Win98; I)

PATH => /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin

HTTP_ACCEPT => image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*

HTTP_CONNECTION => keep-alive

REMOTE_PORT => 3633

SERVER_ADDR => 195.202.122.14

HTTP_ACCEPT_LANGUAGE => en,ru

HTTP_CACHE_CONTROL => max-age=259200

SCRIPT_NAME => /cgi-bin/1.pl

SCRIPT_FILENAME => /usr/local/www/cgi-bin/1.pl

HTTP_ACCEPT_ENCODING => gzip

SERVER_NAME => www.mojdodir.ru

HTTP_PRAGMA => no-cache

REQUEST_URI => /cgi-bin/1.pl

HTTP_ACCEPT_CHARSET => iso-8859-1,*,utf-8

HTTP_X_FORWARDED_FOR => 15.0.0.23

SERVER_PORT => 30

HTTP_HOST => www.mojdodir.ru

SERVER_ADMIN => webmaster@www.mojdodir.ru

HTTP_VIA => 1.0 cache.www.mojdodir.ru:3363 (Squid/2.3.STABLE1)

Непосредственно из скрипта элементы хэша %ENV можно вызывать

$ENV{'HTTP_CACHE_CONTROL'} или $ENV{'HTTP_USER_AGENT'},

смотря что нужно вызывать.

%FORM содержит данные, вводимые из формы методом POST: html форма такая:

<form action="/cgi-bin/1.pl" method="post">

<input type="text" name="name1" size=10 maxlength=10>

<input type="text" name="name2" size=10 maxlength=10>

<input type="text" name="name3" size=10 maxlength=10>

<input type="submit" value="send">

<input type="reset" value="reset"></form>

Если мы введем в поле name1 qwe, name2 rty, name3 asd и нажмем send, то через STDIN передаются данные в виде: name1=qwe&name2=rty&name3=asd и содержимое хэша

%FORM(

name1 => qwe,

name2 => rty,

name3 => asd);

Значения полей name* можно получать $FORM{'name1'}, $FORM{'name2'} и т.д.



Выделение чисел в математической записи


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

#!/usr/bin/perl $_=qq~ 1234 34 -4567 3456 -0.35e-0,2 56grf45 -.034 E20 -.034 e2,01 -,045 e-,23 -,034 e201 3e-.20 -,045 e-,23 e-0.88

4 E-0.20 22 E-21 -0.2 w 4 3 345 2 ^-,3 ~; print "$1\n" while m%(([+-]?(?=\d|[\.,]\d)\d*([\.,]\d*)?((\se|e|\s?\^) ([-+]?\d*[,\.]?)\d+)?)|([+-]?e[+-]?\d*[,.]?\d+))%gxi;

программа исправно выводит все числа. Разберем регулярное выражение

m%(([+-]?(?=\d|[\.,]\d)\d*([\.,]\d*)?((\se|e|\s?\^) ([-+]?\d*[,\.]?)\d+)?)|([+-]?e[+-]?\d*[,.]?\d+))%gxi;

в переменной $1 содержится то, что регулярное выражение находит в результате, т.е. m%(...)%gmi. m%((что-то)|([+-]?e[+-]?\d*[,.]?\d+))%gmi нужно для того, чтобы находить числа вида e-20 или E21(так в математике обозначают десятку в какой-то степени, например e-0,20 = 10-0,20 или E20 = 1021). Рассмотрим левое регулярное выражение "что-то" для чисел вида не e20 или E21:

([+-]?(?=\d|[\.,]\d)\d*([\.,]\d*)?((\se|e|\s?\^)([-+]?\d*[,\.]?)\d+)?)

[+-]? - есть ли в перед числом знак + или -. ? - если вообще есть что-то, находящееся внутри впереди стоящего [...]. Выкинем проверку знака, регексп сократится до

(?=\d|[\.,]\d)\d*([\.,]\d*)?((\se|e|\s?\^)([-+]?\d*[,\.]?)\d+)?

рассмотрим regex (?=\d|[\.,]\d)\d* логический оператор (?=B) требует, чтобы перед числов было B. В данном случае B представляет из себя regex \d|[\.,]\d Regex \d|[\.,]\d значит, что перед каждым числом должно быть что-то либо просто число, либо число, перед которым стоит либо запятая, либо точка, т.е. находим все числа вида ,2 .2 или просто числа 2(2 выбрано для примера, может быть и 3). Далее скобка закрывается и идет \d*, т.е. число вида ,2 точно пройдет(например ,2 e-,23 где перед запятой забыли поставить нолики, но мало ли бывает, забыли, надо и это предусмотреть. Вообще когда пишешь программу, надо предполагать, что е использовать будет ленивый склеротический чайник, правда не всегда возможно предугадать что учудит юзер, но к этому надо стремится), а вот число вида ,223 не пройдет. Да и regex (?=\d|[\.,]\d) говорит о том, что нужно найти только одну цифру после запятой. Для остальных цифр и нужен квантификатор \d*, который значит любое количество цифр, в том числе и ноль, т.е. оно работает и для числе вида .2 или ,2 Далее идет регулярное выражение ([\.,]\d*)? которое говорит о том, есть ли вообще точка и запятая(здесь всю полную строчку в принципе можно усовершенствовать) и число \d*(в том числе и его отсутствие, ведь квантификатор * значит любой символ в том числе и ноль). Отбрасывая все что было выше от этого большого регулярного выражения остается строчка:


((\se|e|\s?\^)([-+]?\d*[,\.]?)\d+)?

Эта строчка отвечает за поиск в строке $_ математических обозначений степеней типа e201, E,20(число в степени 0,20 например a-0,20) и т.д. но только для подстрок вида -,034 e201. Заметьте, что в конце стоит знак вопроса, т.е. если степенное обозначение вообще существует. (\se|e|\s?\^) есть ли числа вида -,034 e201 или -,034e201 и числа в "компьютерной" записи вида 2 ^-,3 = 2-0,3, т.е. этим регекспом мы разрешили пользователю ставить или не ставить пробел при указании степени и разрешили писать значек ^ с пробелом перед ним(если есть). Далее идет выражение ([-+]?\d*[,\.]?), которое говорит о том, что степень может быть с + или - (типа e,-23 где юзер забыл поставть нолик, а на самом деле хотел написать a-0,23). Дальше идет цифра \d* (а может и не идет, т.к. квантификатор то *). Потом идет либо точка либо запятая(причем тут негласно введено ограничение на использование запятой/точки, после e, если степень дробная или вообще есть, точка или запятая должна быть, иными словами не имеет смысла написать -2,34e-,23, хотя юзер на самом деле хотел написать число -2,34-0,23). Наконец мы добрались до конца: идет \d+, но тут уж, пользователь, будь добр напиши хотя бы одно число, т.к. квантификатор +, а не * после \d. Т.е. наложили своего рода ограничения здравого смысла, можно просто написать 2, а можно написать и 2e,- что суть бессмыленно. И еще, m%(что-то)%igm стоит квантификатор i, который разрешает e быть и заглавным и квантификатор x, который разрешает разносить регулярное выражение на несколько строк.

Прошу прошения что не ставил иногда знаки препинания, которые есть точка и запятая, тогда Вы бы подумали, что что-то лишнее написно и не подсечено как спецсимвол при помощи бэкслэша \.

Итак, регулярным выражением m%(([+-]?(?=\d|[\.,]\d)\d*([\.,]\d*)?((\se|e|\s?\^) ([-+]?\d*[,\.]?)\d+)?)|([+-]?e[+-]?\d*[,.]?\d+))%gxi;

были предусмотрены числа степенного порядка, просто числа, числа со знаком, нецелые числа вида ,3(которое есть 0,3 или 0.3), ошибки пользователя при вводе чисел( типа -.034 e2,01 хотя надо бы писать либо -,034 e2,01 либо -.034 e2.01 хотя по смыслу перед точками и запятыми нужно ставить нули, но мы предусмотрели и это) и числа в "компьютерном" представлении.

Конечно, данное регулярное выражение не претендует на абсолютную работу, т.к. оно успешно не работает на подстроках вида -,045 e -,23 e-0.88 считая -,045 отдельным числом, а -,23 возводит в степень e-0.88, хотя по идее должно было бы быть два числа -,045 e -,23 и e-0.88, в таком случае еще одно ограничение пользователю: если хочется, чтобы степенные числа понимались корректно(для этой программы), то нельзя ставить пробел перед степенью e.


Для того чтобы организовать циклы


Для того чтобы организовать циклы по элементам хэша, нужно использовать функцию each:
%hash = (
'шляпа' => 'серая',
'водка' => 'горькая',
'вобла' => 'вкусная');
while(($key,$value) = each %hash){
print "$key => $value\n";
};
Для перебора элементов не очень большого хеша можно воспользоваться foreach:
%hash = (
'шляпа' => 'серая',
'водка' => 'горькая',
'вобла' => 'вкусная');
foreach $key(keys %hash){
print $key,"\n"; #возвращает список ключей хеша
}
%hash = (
'шляпа' => 'серая',
'водка' => 'горькая',
'вобла' => 'вкусная');
foreach $value(values %hash){
print "$value\n"; #возвращает список значений хеша
}
Преимущество each заключается в том, что пары ключ/значение извлекаются по одной, Если хэш содержит слишком много ключей, отказ от предварительного построения полного списка существенно экономит память и время, но функция each не позволяет управлять порядком обработки пар. Перебор хэша при помощи while затрачивает мало памяти. Можно любым образом форматировать выходные данные, при этом нужны всего лишь две скалярные переменные, ключ и значение.
Цикл foreach перебирает заранее построенный список ключей, поэтому после начала цикла он ничего не знает о добавленных или удаленных ключах, ключи, добавляемые внутри цикла, не включаются автоматически в список перебираемых ключей, а удаленные внутри цикла ключи не удаляются из этого списка.
Содержимое хэша можно вывести и так:
while (@Res = each %hash){
print "$Res[0] = $Res[1]\n"
}
Вывод хэша одной строкой.
можно воспользоваться функцией map:
print map {"$_ => $hash{$_}\n"} keys %hash;
функция map позволяет работать с элементами в произвольном порядке, в этом случае создается список строк(ключ => значение), передаваемый функции print. Если сохранить хэш во временном массиве, то он будет выведен как строка:
{
my @temp = %hash;
print "@temp";
}
также можно вывести хэш и таким образом:
print "@{[%hash]}\n";


в двух последних случаях мы интерполируем хэш как список, что не позволяет предсказать или управлять порядком вывода пар "ключ/значение". Данные в последних двух случаях выводятся в виде списка ключей и значений, элементы которого разделяются текущим содержимым переменной $", т.е. не удастся вывести каждую пару значений на новой строке или отделить ключи от значений каким-либо символом. Приведем программу, которая читает файл почтового ящика и выводит количество сообщений от каждого отправителя, отправитель определяется по строке From(цель программы только проиллюстрировать операции с хешами):
#!/usr/bin/perl -w
$file = $ARGV[0] || "-";
open(FILE, "
Запускаем программу чтения почтового ящика: bash-2.03$ ./1.pl /usr/home/vovka/mbox
Инвертирование хэша производится при помощи функции reverse, в котором ассоциированные значения исходного хэша являются ключами и наоборот. Воспользуемся списковой эквивалентностью хэшей. В списковом контексте reverse иетерпретирует %hash как список и меняет местами составляющие его элементов. Например: имеем хэш %Glavfish = ("seledka"=>"mokraia","skat"=>"elektricheskij"), если его интерпретировать как список, то получим следующее ("seledka","mokraia","skat","elektricheskij"), после инвертирования список выглядит так: ("elektricheskij","skat","mokraia","seledka"), интерпретация его как хэша дает следующее: ("elektricheskij"=>"skat","mokraia"=>"seledka").

Вывод хеша в порядке вставки без использования Tie::IxHash


Без модуля Tie::IxHash вывод хеша в порядке вставки можно сделать при помощи дописывания числовой информации в хеш. Есть файл news.dat, который выводится скриптом в таком порядке, в каком данные занесены в файл. Необходимо удалить одновременно больше одной строчки из текста(не важно строка это, или разделитесь, это однозначно определяется переменной $/).

#!/usr/bin/perl -wT

use CGI 'param';

@del=param;

sub del{

pop @del; $mass=~s!"|&(.*?);!!g;

open F, "<news.dat" or die "Err: $!"; @mass=<F>; close F;

open F, ">news.dat";

foreach $un(@mass){ $as=$un; $i++; chomp $as;

$un=~s|(.*)new>(.*?)</a>(.*)\[(.*?)\]|$2$4|i;

$un=~s!"|&(.*?);!!g; chomp $un;

$u{"$un"}="$as#$i#\n";

}

foreach $del(@del){

$del=~s!"|&(.*?);!!g; chomp $del;

$terr="Link $u{$del} was deleted<p>\n" if (exists $u{"$del"});

$terr=~s!\d{8}|#(.*?)#!!ig;

print $terr; $terr="";

delete $u{$del} if (exists $u{"$del"});

}{ local $_;

while (($km, $_) = each %u){ push @tmp, "$u{$km}"}

}

@temp=grep{s/#(\d+?)#//}

map{ $_ -> [1]}

sort{$a->[0] <=> $b->[0]}

map{[/#(\d+?)#/, $_]}

grep{!$_{$_}++} @tmp;

print F reverse @temp;

close F;

}

Разъясним принцип работы скрипта. Исходная задача такова: на входе есть несколько checkbox из формы, в которых может быть поставлено больше одной галочки. Требуется найти и вычеркнуть отмеченные строчки. Файл news.dat модержит строки вида:

12345678<a href="lalalal">tra-ta-ta</a>&nbsp;&nbsp;&nbsp;[AAA]

чекбокс отмечается текстом tra-ta-ta, т.е. что-то вида

for ($i=$pos; $i<$pos+$n; $i++) {

$res[$i]=~s|^(\d\d\d\d)(\d\d)(\d\d)|$3\.$2\.$1 |;

print qq~<tr><td>$res[$i]</td><td>

<input type=checkbox name="$1$3" value="$1$3"></td></tr>~

if($res[$i]=~m!>(.*?)</a>(.*?)\[(.*?)\]!);

}

т.е. name="$1$3" value="$1$3" => name=tra-ta-ta&value=tra-ta-ta. Идея заключается в том, что элементы хеша можно пронумеровать в исходном порядке вставки, который будет исходным в силу того, что хеш определяется foreach, который последовательно читает данные из массива. поэтому говорим $i++; в цикле, ставим цифру в разделителе #\d+# и получаем на выходе хеш:


foreach $un(@mass){ $as=$un; $i++; chomp $as;
$un=~s|(.*)new>(.*?)</a>(.*)\[(.*?)\]|$2$4|i;
$un=~s!"|&(.*?);!!g; chomp $un;
$u{"$un"}="$as#$i#\n";
}
Дальше начинаем в хеше искать данные, которые передались через @del=param;
foreach $del(@del){
$del=~s!"|&(.*?);!!g; chomp $del;
$terr="Link $u{$del} was deleted<p>\n" if (exists $u{"$del"});
$terr=~s!\d{8}|#(.*?)#!!ig;
print $terr; $terr="";
delete $u{$del} if (exists $u{"$del"});
}
при помощи функции exists проводится проверка на наличие элемента в хеше. Итак, получили хеш с ключами, являющимися подстроками строк из файла news.dat, и значениями самих строк, т.е. в памяти точно лежит файл, превосходящий по размеру news.dat чуть меньше чем в два раза.
Далее идет вытаскивание значений из файла, уже без удаленных(было сравнение по подстроке):
{ local $_;
while (($km, $_) = each %u){ push @tmp, "$u{$km}"}
}
Замечательно, проверили, занесли в массив @tmp. Здесь локализация local $_; применена для того, чтобы убрать при использовании ключа -w лишнего warning из серверного лог-файла ошибок. Вытащили новый массив, который нужно соранить в файл news.dat. Теперь нужно убрать из массива @tmp повторяющиеся элементы, отсортировать по номерам #(\d+)#, убрать эти номера из элементов массива @tmp и сохранить массив в прежнем виде:
@temp=grep{s/#(\d+?)#//}
map{ $_ -> [1]}
sort{$a->[0] <=> $b->[0]}
map{[/#(\d+?)#/, $_]}
grep{!$_{$_}++} @tmp;
print F reverse @temp;
операция grep{!$_{$_}++} удаляет из массива повторяющиеся элементы, map{[/#(\d+?)#/, $_]} создает временный список анонимных массивов, которые затем сортируются sort{$a->[0] <=> $b->[0]}, затем map{ $_ -> [1]} приводит элементы массива в удобоваримый вид и grep{s/#(\d+?)#//} вырезает нуумерацию массива, оставшуюся от начального формирования хеша %u.
Далее оборачиваем конечный массив @temp функцией reverse и получам такой-же файл news.dat, только без элементов, отмеченных пользователем в чекбоксе.
Еще один вывод хеша в порядке вставки без использования приспособленных
для этого модулей:
my @qq = qw(a s d f g h j y f d e e t y u i v f s a e);
my @del = qw(f h u);
my (%to, %del, %exist);
map {$del{$_} = 1} @del;
for (my $i=$#qq; $i>=0; $i--){
if (!exists $exist{$qq[$i]}){
$exist{$qq[$i]} = 1;
$to{$i} = $qq[$i] unless(exists $del{$qq[$i]});
}
}
my @tmp;
foreach (sort{$a$b} keys %to){
push @tmp, $to{$_};
print "$to{$_}\n";
}
автор: Monax from http://www.rt.mipt.ru/board

Вывод хеша в порядке вставки с использованием Tie::IxHash


Для перебора элементов хэша в порядке вставки, т.к. keys и each выводят элементы хеша неупорядоченно, можно воспользоваться модулем(либо операциями с массивами) Tie::IxHash

use Tie::IxHash

tie %hash, "Tie::IxHash";

#операции с %hash

@keys = keys %hash;

Модуль Tie::IxHash заставляет функции keys, each и values возвращать элементы в порядке занесения их в хэш. Если у Вас нет такого модуля IxHash.pm то нужно зайти на CPAN/modules, найти его и установить, если у вас нет прав на установку библиотек, то в первой строчке скрипта нужно написать #!/put'/do/perl'a -wT -I/put'/do/nugnogo/modulia и установить модуль в Вышей домашней директории. Пример использования Tie::IxHash:

use Tie::IxHash

tie %hash, "Tie::IxHash";

%hash = (

'шляпа' => 'серая',

'водка' => 'горькая',

'вобла' => 'вкусная');

print "В упорядоченной вставке список хеша такой:\n";

foreach $qwerty (keys %hash){

print " $qwerty\n";

}

print "Кроме того, предметы обладают некоторыми свойствами:\n";

while(($predmet, $opredelenie) = each %hash){

print $predmet $opredelenie,"\n";

}

см. тех документацию по модулю Tie::IxHash.



Вывод результатов поиска


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

$sn=4; { local $_=$description1; print "...$1<font color=red>$3</font>$4..." while(m/(([\s,\.\n^]*\w*){$sn})(\s*$query\s*)(([\s,\.\n^]*\w+){$sn})/ig); } $_="";

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

Соответственно из вида регекспа понятно, что разделителями слов могут быть символы [\s,\.\n^]*, в том числе и символ перевода каретки ^. Комбинация (\d\d\d){$sn} значит что нужно начти 3 цифры три раза.



WWW,CGI-специфика


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


При попытке запустить скрипт происходит 500 Internal Server Error! Что это за ошибка?


Как узнать IP человека, вызвавшего скрипт?


Как узнать, с какой страницы идет ссылка на скрипт?


Как узнать IP прокси, если через нее запустили скрипт?


А можно ли узнать IP юзера, запустившего скрипт через прокси?


А какие еще значения есть у этого %ENV?


Как запускать скрипт на сервере через определенные промежутки времени, или в определенное время суток, день недели, месяц?


Как, зная ip, получить имя (DNS), за которым этот ip закреплен?


Что такое method GET, и что такое method POST?


Как обрабатывать параметры, переданные скрипту?


Посоветуйте халявный хостинг с поддержкой CGI-perl.


Что надо указатьв заголовках HTTP-ответа CGI скрипта, выводящего содержимое, которое надо не показать на экране, а сохранить в файле с заданным именем, например 'download.zip' ? А то браузер сохраняет файл с именем скрипта.


Директивы SSI не обрабатываются в выводе скрипта. Что делать?



print "Ok";

Обратите внимание на двойной перевод строки в конце заголовка.

(*)Примечание:

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

директиву use CGI::Carp qw (fatalsToBrowser); В этом случае при фатальной ошибке, приводящей к завершению скрипта, эта ошибка будет видна вам в браузере.

Q: Как узнать IP человека, вызвавшего скрипт?

A: $ENV{'REMOTE_ADDR'}

Q: Как узнать, с какой страницы идет ссылка на скрипт?

A: $ENV{'HTTP_REFERER'}

Q: Как узнать IP прокси, если через нее запустили скрипт?

A1 $ENV{'HTTP_VIA'}

A2: Hекоторые прокси добавляют в конец заголовка строку типа

", via ProxyName", и в результате вместо переменной HTTP_VIA эту строку можно

наблюдать в конце переменной $ENV{'HTTP_USER_AGENT'}

Q: А можно ли узнать IP юзера, запустившего скрипт через прокси?

A: $ENV{'HTTP_X_FORWARDED_FOR'}. Hо не все прокси обеспечивают IP сидящего за

ними юзера. "Честные" прокси,- у провайдеров, например,- это делают. А

некоторые халявные (анонимные) прокси-сервера, могут и не показывать IP сидящего "за" ними пользователя.

Q: А какие еще значения есть у этого %ENV ?

A: for (keys %ENV) { print "$_ = ${ENV{$_}}\n" }

A1: То же самое, но по-другому записанное (более "перловое" решение):

print join("
",map("$_ = $ENV{$_}", keys %ENV));

Q: Как запускать скрипт на сервере через определенные промежутки времени, или

в определенное время суток, день недели, месяц?

A: Это возможно, если есть шелл-доступ на сервер. Читайте man crontab

Q: Как, зная ip, получить имя (DNS), за которым этот ip закреплен?

A: Встроенная функция gethostbyaddr()

Q: Что такое method GET, и что такое method POST?

A1: rfc2616

A2: GET - передача параметров скрипту из строки location браузера. Пример:

script.cgi?mode=aa&type=bb&length=12

Минусы этого метода:

1. Все параметры видны в строке. Если в кач-ве параметров передается пароль

- получается дырка в безопасности



2. Длина данных, передаваемых таким методом, ограничена.

3. Hельзя передавать multipart form data, в т.ч. файлы через кнопочку

"Browse"

POST - передача данных скрипту через STDIN. Отсутствуют минусы метода GET.

Обычно метод GET используется, когда скрипт вызывается со страницы через линк

, а POST - при нажатии кнопки submit в форме.

О получении параметров внутри скрипта читайте в следующем Q.

Q: Как обрабатывать параметры, переданные скрипту?

A1: Используйте модуль CGI. Прочтите perldoc CGI , а для начала простой

пример:


use CGI;

$q=new CGI();

$mode=$q->param('mode');

$q - объект, который имеет несколько методов и полей, относящихся к

параметрам вызова, переменным окружения, cookie, и пр. В $mode содержится значение параметра 'mode'.


или проще: use CGI qw/:standard/;

$mode=param('mode'); если вам не нужно несколько объектов.


A2: Некоторые предпочитают пользоваться библиотекой cgi-lib (она тоже входит в модуль CGI, хотя существуют индивидуумы, которые включают ее отдельным файлом).

Пример:

use CGI qw(:cgi-lib);

ReadParse(); #Функция возвращает все параметры в хэш.

$mode=$in{'mode'};

A3: Можно пойти по пути изобретения велосипеда и начать переписывать модуль CGI, т.е. разбор параметров метода GET, потом наверняка понадобиться POST, а потом multipart form data. В написанный код закрадуться ошибки, которые придется отлавливать на последующих этапах. Это конечно дает неплохую практику программирования, но лучше просто посмотрите как написан модуль CGI.

(Высказанное в последнем ответе является тем самым ИМХО ).

Q: Посоветуйте халявный хостинг с поддержкой CGI-perl.

A:www.virtualave.net

free.prohosting.com

www.hypermart.net

www.virtualave.net

www.webservis.ru

www.h1.ru

www.holm.ru

www.hut.ru

Примечание:

В последнее время почти все халявные хостинги перестали поддерживать исходящие запросы, т.е. скачать откуда-нибудь файл используя LWP или Net::Ftp не получиться.

Если знаете хостинг с поддержкой исходящих запросов, напишите мне, буду благодарен.

Q: Что надо указатьв заголовках HTTP-ответа CGI скрипта, выводящего

содержимое, которое надо не показать на экране, а сохранить в файле с заданным

именем, например 'download.zip' ? А то браузер сохраняет файл с именем скрипта.

A: print "Content-Type: application/octet-stream\nContent-Length: ", -s 'download.zip' ,"\n";

print "Content-Disposition: attachment; filename=download.zip\n\n";

Q: Директивы SSI не обрабатываются в выводе скрипта. Что делать?

A: Есть специальный модуль - CGI::SSI.


Зачем нам нужны эти скрипты?


Форум, чат, доска объявлений, голосование, гостевуха, каталог, топ, магазин и аукцион - все это можно сделать с помощью CGI. Возникает вопрос, что такое скрипт? Грубо говоря, скрипт - это программка, которая запускается не на вашем компьютере, а на сервере. В результате работы скрипта, сайт превращается из существа пассивного, в существо активное, у вас появляется больше возможностей как для общения с посетителями (форумы, чаты, mail формы, опросы, голосования, рассылки), так и в управлении сайтом (организация оперативно обновляемых новостей, баннерокрутилка, публикация статей через веб и т.д.) Кроме того, некоторые скрипты могут стать основой вашего сайта (например, каталог, топ-рейтинг, служба поздравительных открыток, поисковая машина…) - у вас уже загорелись глаза? То-то же, скрипты открывают новые горизонты, у кого-то появляются нездоровые желания создать свой Yahoo!, а кто-то просто хочет сделать на сайте гостевую книгу.



Заголовки запросов и ответов


Даже если вы и знаете кое-что о HTTP все равно не лишне будет вспомнить о том как это все работает тем более на эту информацию придется ориентироваться при написании CGI скриптов.

Этапы соедирения.

Первый этап это когда HTTP -клиент(браузер) соединяется с сервером.для этого он использует протокол TCP/IP соединение происходит к известному клиенту TCP-порту (80 -номер порта HTTP) (другие сервисы сидят на других портах ,например FTP и SMTP на 21 и 25)

Вторым этапом идет запрос клиента:клиент передает заголовок запроса и возможно(в зависимости от метода) тело сообщения запроса.В заголовке обязательно указывается метод ,URI,и версия HTTP,и может быть еще несколько необязательных полей

Третий этап -ответ сервера,который опять таки состоит из заголовка,в котором сервер указывает версию HTTP и код статуса, который может говорить о успешном или неуспешном результате и его причинах.Далее идет тело ответа.

Четвертым этапом происходит разрыв TCP/IP соединения.

HTTP -запрос.

Запрос состоит из Строки запроса(она обязательна) и остальных полей. Синтаксис строки :МЕТОД <SP> URI <SP> HTTP/версия <CRLF>

где <SP> -пробел ,<CRLF> -переход на новую строку

Методы HTTP.

GET

Самый часто применяемый метод,в протоколе HTTP/0.9 был единственным методом,и применяется для извлечения информации по заданому URI

Может быть условным если в заголовке указано поле If-Modified-Since:

HEAD

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

POST

передает данные для обработки их программой ,указаной в URIсдесь обязательно указывается поле Content-Length:

Сушествуют и другие ,реже применяемые методы,например PUT -для сохранения передавемых данных в указаном URI

и DELETE для удаления ресурса.

Поля заголовка запроса.

После строки запроса идут поля заголовка запроса.

Поля общего(general-header) заголовка (он общий как для запросов так и для ответов):


Date:

Указывает дату запроса,например:

Date: Sun, 20 Nov 1994 08:12:31 GMT

MIME-version:

Указывает версию MIME (по умолчанию 1.0)

MIME-version: 1.0

Pragma:

Содержит указания для таких промежуточных агентов как прокси и шлюзы,

Pragma: no-cache

Поля относящиеся к запросу(Request-Header):

Authorization:

Содержит информацию аутентификации

Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

From:

Браузер может посылать адрес пользователя серверу

From: quake@doom.ru

If-Modified-Since:

используется при методе GET ресурс возвращается ,если он был изменен с указаного момента, может использоваться при кешировании.

If-Modified-Since:Mon 15 Jul 1997 00:15:24 GMT

Referer:

Содержит URL предшествующего ресурса.

Referer: http://www.uic.nnov.ru/~paaa/index.html

User-Agent:

Програмное обеспечение клиента.

User-Agent: Mozilla/3.0

Заголовок информации сообщения (Entity-Header) применяется как в запросах так и в ответах (при этом некоторые поля только в ответах):

Allow: (в ответе сервера)

Список методов,поддерживаемых ресурсом.

Allow: GET, HEAD

Content-Encoding:

идентифицирует метод кодировки,которым был закодирован ресурс

Content-Encoding: x-gzip

Content-Length:

Длина тела сообщения

Content-Length: 102

Content-Type:

Содержит тип ресурса(MIME),для текстовых еще и кодировку символов(необязательно)

Content-Type: text/html; charset=windows-1251

Expires: (в ответе сервера)

Дата окончания действия ресурса,применяется в кешировании для запрета кеширования устаревших ресурсов (в ответе)

Expires: Tue, 24 Sep 1998 23:00:15 GMT

Last-Modified: (в ответе сервера)

Время последнего обновления ресурса

Last-Modified: Tue, 23 sep 1998 13:48:40 GMT

Другие поля:

Поля Accept: указывают серверу выдавать только указаные форматы данных,которые клиент может распознать.

Accept: text/html

Accept: text/plain

Accept: image/gif

Примеры запросов:



Простейший запрос: GET /index.html HTTP/1.0

Посложнее: GET /somedir/somedoc.html HTTP/1.0 User-Agent: Mozilla/2.0 Accept: text/html Accept: text/plain Accept: image/gif



Передача данных CGI- скрипту через метод GET GET /~paaa/cgi-bin/test.cgi?name=Dmitry&organization=%D3%ED%E8%E2%E5%F0%F1%E8%F2%E5%F2+%CD%E8%E6%ED%E5%E3%EE+%CD%EE%E2%E3%EE%F0%EE%E4%E0&Name=&email=&comment= HTTP/1.0 User-Agent: Mozila/2.0 Accept: text/html Accept: image/gif

Используя метод POST данные передаются в теле сообщения запроса: GET /~paaa/cgi-bin/test.cgi HTTP/1.0 User-Agent: Mozila/2.0 Accept: text/html Accept: image/gif Content-Type: application/x-www-form-urlencoded Content-Length: 131

name=Lesha &organization=%D3%ED%E8%E2%E5%F0%F1%E8%F2%E5%F2+%CD%E8%E6%ED%E5%E3%EE+%CD%EE%E2%E3%EE%F0%EE%E4%E0&Name= &email= &comment=

Ответ HTTP-сервера.

Ответ идет от сервера.Состоит он из строки состояния и затем поля ответа Общий заголовок(General-Header) и заголовок тела сообщения (Entity-Header),которые уже описаны при обсуждении запроса. и еще идет заголовок ответа(Response-Header).

Строка состояния имеет следующий формат:

HTTP/version <SP> Status-Code <SP> Status-Phrase

где HTTP/version версия,Status-Code -3х значный код,и Status-Phrase текстовая фраза, поясняющая код ,пример: HTTP/1.0 200 Ok

,200 -код означающий успешную обработку запроса,что и поясняет "Ok"

Заголовок ответа состоит из полей:

Location:

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

Location: http://www.uic.nnov.ru/newlocation/index.html

Server:

Информация о програмном обеспечении сервера

Server: Apache/1.1

WWW-Autenticate:

Параметры аутентификации.

WWW-Autenticate: Basic realm="doomsday"

Коды ответов HTTP.

Код статуса Значение
200 OK
201 Успешная команда POST
202 Запрос принят
203 Запрос GET или HEAD

выполнен
204 Запрос выполнен но нет содержимого
300 Ресурс обнаружен в нескольких местах
301 Ресурс удален навсегда
302 Ресурс отсутствует временно
304 Ресурс был изменен
400 Плохой запрос от клиента
401 Неавторизованый запрос
402 Необходима оплата за ресурс
403 Доступ Запрещен
404 Ресурс не найден
405 Метод не применим для данного ресурса
406 Недопустимый тип ресурса
410 Ресурс Недоступен
500 Внутренняя ошибка сервера

(это по вашу душу,юные CGI-программисты ;( )
501 Метод не выполнен
502 Неисправный шлюз либо перегруз сервера
503 Сервер недоступен/тайм-аут шлюза
504 Вторичный шлюз/тай-аут сервера
<


Более подробное описание всех кодов можно найти в RFC-1945

Несколько примеров:



HTTP/1.0 200 Ok Date: Wed, 25 Sep 1998 23:00:00 GMT Server: Apache/1.1 MIME-version: 1.0 Last-Modified: Mon 15 Nov 1996 15:20:12 GMT Content-Type: text/html Content-Length: 2000

<HTML><HEAD><TITLE>Hello</TITLE></HEAD> <BODY bgcolor="green" text="yellow"> ...... </HTML> А вот такое сервер выдаст в неудачном случае: HTTP/1.0 404 Not Found



CGI-заголовок.

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

Заголовок (CGI-Header) состоит из полей:

Content-Type:

Должно обязательно присутствовать,если есть тело.

Content-Type: text/html

Location:

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

Location: http://www.idsoftware.com/index.html

Status:

Позволяет CGI скрипту вернуть статус обработки,если это поле не задано,то сервер подразумевает "200 Ok"

Status: 404 Not found

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

Примеры:



Обычно такое выдает скрипт: Content-Type: text/html

<HTML><HEAD>....... Но иногда такое(когда он служит для перенаправления): Location: http://www.mustdie.ru/

А вот пример возврата статуса: Content-Type: image/gif Status: 190 Its seems great like a playing doom! WOW!

GIF89a........

nph-скрипты.

Иногда возникает необходимость чтобы CGI -скрипт сам отвечал напрямую клиенту, минуя разбор заголовка.Это во-первых уменьшает нагрузку на сервер,и во вторых, что самое главное такой прямой ответ клиенту позволяет скрипту полностью контролировать транзакцию.Для этого существуют nph-скрипты(Not Parse Header) ,имя скрипта должно начинаться с префикса "nph-" ,Например "nph-animate.cgi" .Такие скрипты сами формируют HTTP-ответ клиенту,что полезно при анимации:





#!/usr/bin/perl #nph-animate.cgi

$times = 20; #Заготовте несколько небольних gif-файлов для этой программы @files = qw(img0.gif img1.gif img2.gif img3.gif);

select (STDOUT); $|=1; #autoflush mode on #Generate header print "HTTP/1.0 200 Okay\n"; print "Content-Type: multipart/x-mixed-replace;boundary=myboundary\n\n";

print "--myboundary\n"; for ($num=1;$num<=$times;$num++) { foreach $file (@files) { print "Content-Type: image/gif\n\n"; open(PIC,"$file"); print <PIC>; close(PIC); print "\n--myboundary\n"; sleep(3); } } print "\n--myboundary--\n";

Этот пример вам выдаст анимацию ,составленую из нескольких .gif -файлов.Если же вы получили вместо анимации сообщение об ошибках,то вам следует,может быть перейти к следующей главе, которая поведает вам о правах доступа- того,без чего Unix не был бы Unixом.


Загрузка файлов на сервер через Интернет.


Файлы можно загружать на веб-сервер через Интернет,используя формы.Вы,наверное,сами не раз это делали.Разберем более подробно,как это делается. Нужно создать форму с полем типа file и методом кодировки multipart/form-data.

#!/usr/local/bin/perl

print "Content-type:text/html\n\n"; print <<HTML; <html><head>

<script language="javascript">

<!-- function fill () { if (fn==document.form.entry.value) { document.form.file.value=fn; } } //-->

</script>

</head>

<body bgcolor="e6e8fa">

HTML print "<p><table width=300 bgcolor=\"bfbfbf\">\n"; print "<h3 align=center><font color=\"0000ff\">File upload:</font></h3>\n"; print "<center><FORM action=\"../cgi-bin/upload.cgi\" name=\"form\" METHOD=\"POST\" ENCTYPE=\"multipart/form-data\">\n"; print "<tr><td align=center><b>Select file:</b></td>\n"; print "<tr><td><input type=\"file\" name=\"entry\" onBlur=\"fill()\"></td>\n"; print "<tr><td><input type=\"hidden\" name=\"file\" value=\"1\"></td>\n"; print "<tr><td align=center><input type=\"Submit\" value=\"Upload\"></td></table>\n"; print "</form></center></table></body></html>\n";

Функция Javascript использована для того,чтобы передать на сервер имя загружаемого файла, включая полный путь.Далее,скрипт декодирует его,отбросит путь и загрузит файл под его именем. Функцию для декодирования в этом случае я использую готовую,нашел в Интернете,за что большое спасибо ее разработчику.

$content_type = $ENV{'CONTENT_TYPE'}; binmode STDIN; read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); if ((!$content_type) || ($content_type =~ m#^multipart/form-data#)){ ($boundary = $content_type) =~ s/^.*boundary=(.*)$/\1/; @pairs = split(/--$boundary/, $buffer); @pairs = splice(@pairs,1,$#pairs-1); for $part (@pairs) { ($dump,$fline,$value) = split(/\r\n/,$part,3); next if $fline =~ /filename=\"\"/; $fline =~ s/^Content-Disposition: form-data; //; (@columns) = split(/;\s+/, $fline); ($name = $columns[0]) =~ s/^name="([^"]+)"$/\1/g;


if ($#columns > 0) { if ($value =~ /^Content-Type:/) { ($dump,$dump,$value) = split(/\r\n/,$value,3); } else {($dump,$value) = split(/\r\n/,$value,2);}} else {($dump,$value) = split(/\r\n/,$value,2); if (grep(/^$name$/, keys(%CGI))) { if (@{$FORM{$name}} > 0) { push(@{$FORM{$name}}, $value);} else { $arrvalue = $FORM{$name}; undef $FORM{$name}; $FORM{$name}[0] = $arrvalue; push(@{$FORM{$name}}, $value);}} else { next if $value =~ /^\s*$/; $FORM{$name} = $value;} next;} $FORM{$name} = $value;}}

Как видите,довольно сложная и громоздкая,зато загрузка проходит без проблем. Далее нужно получить имя файла и отбросить путь,оставив только имя.

$upfile=$FORM {'entry'}; #Имя загружаемого файла. $destfile=$FORM {'file'}; #Имя,под которым он будет записан в каталог назначения. $destdir="/home/upload"; #Имя каталога для загрузки. chdir ("$destdir");

#Отбрасываем путь,оставляя только имя. $destfile=~s/\w+//; $destfile=~s/([^\/\\]+)$//; $destfile=$1;

#Далее записываем файл в каталог назначения. open(FILE, ">$destdir/$destfile"); #Открываем на запись новый файл. binmode FILE; #Устанавливаем бинарный режим. print FILE $upfile; #Записываем в него содержимое загруженного файла. close(FILE); #Закрываем файл.

Все,загрузка завершена.Таким способом можно загружать сразу несколько файлов-5 или 10,создав для каждого элемент формы и,само собой,добавив в скрипте нужное количество обработчиков.


Форматы.


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

Оператор format имеет следующий синтаксис:

format имя = FORMLIST .

Обратите внимание на то, что описание формата идет после строки format и заканчивается символом '.' в начале строки.

Здесь 'имя' - это имя формата, такое же как и имя указателя выходного файла. Если 'имя' отсутствует то значение по умолчанию - STDOUT.

FORMLIST - это строки формата. Они бывают трех типов:

Комментарий. Строка начинается символом '#'.

Описатель полей данных (picture).

Строка аргументов используемых описателем.

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

Размер и вид поля в описателе обозначается следующими символами:

"<<<<" - выравнить значение по правому краю.
">>>>" - -//- по левому.
"||||" - -//- по центру.
"####.###" - формат числа с точкой.
"@*" - многострочная строка. Данные выводятся в колонку.

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

Символ '^' в начале поля имеет специальное значение.

Так:

"^####" - пусто если переменная не определена.

для строчного скаляра:

"^

Пример:

#!/usr/local/bin/perl # # Программа печати пригласительного билета # $кому = "Чапаеву Василию Ивановичу"; $от_кого = "Компания МММ"; $адрес = "Москва, ул. Петровка, д 38"; $текст = "Уважаемый Василий Иванович! Компания МММ имеет честь пригласить Вас и Ваших близких на презентацию наших новых хромовых сапог, сделанных на уровне мировых стандартов качества и дизайна."; format STDOUT =


П Р И Г Л А С И Т Е Л Ь Н Ы Й Б И Л Е Т ---------------------------------------------------------------------- Кому: @

Результат:

П Р И Г Л А С И Т Е Л Ь Н Ы Й Б И Л Е Т ---------------------------------------------------------------------- Кому: Чапаеву Василию Ивановичу | Уважаемый Василий Иванович! | Компания МММ имеет честь От кого: Компания МММ | пригласить Вас и Ваших близких | на презентацию наших новых Адрес:Москва, ул. Петровка, д 38 | хромовых сапог, сделанных на | уровне мировых стандартов | качества и дизайна. | ---------------------------------------------------------------------- Отпечатано в типографии ИТУ 38

Специальные переменные:



$~ - построчный формат содержимого.

$^ - формат заголовка листа.

$% - номер листа.

$= - строк в листе.

Если вы хотите использовать одни и те же форматы для разных файлов, то самый простой путь:

use FileHandle; # Указать в начале программы format_name файл имя_формата; # Формат содержимого листа. format_top_name файл имя_формата; # Формат заголовка листа. write(файл); # вывод данных.

Здесь 'файл' имеется ввиду указатель файла полученный командой open();

Если вам нужно в теле листа выводить разного рода форматы (например заголовки групп или отбивку листа), то применяйте format_name.

[Назад] [Содержание] [Вперед]


INFO-DOS


==========================================

== ЃЁЎ«Ё®вҐЄ  Є®¬ЇмовҐа­®© ¤®Єг¬Ґ­в жЁЁ ==

============ 'Roga Ё Љ®Їлв ' =============

==========================================

============ www.roga.by.ru ==============

==========================================

ЏаЁе®¤ЁвҐ Ё ®Єг­ЁвҐбм ў ¬Ёа ўЁавг «м­®©

Ё­д®а¬ жЁЁ. - www.roga.by.ru

==========================================

==========================================



Info-win


==========================================

== Библиотека компьютерной документации ==

============ 'Roga и Копыта' =============

==========================================

============ www.roga.by.ru ==============

==========================================

Приходите и окунитесь в мир виртуальной

информации. - www.roga.by.ru

==========================================

==========================================



Интернет - ссылки и литература.


Очень полезные USENET конференции:

comp.lang.perl.announce - Различные объявления и сообщения.

comp.lang.perl.misc - Место для вопросов и обсуждений.

comp.lang.perl.modules - Модули Perl.

comp.lang.perl.tk - Perl и Tcl/tk.

WWW сервера:

Специальный Perl-сервер

Книги по Unix издательства O`Reily

Специализированный FTP сервер

Список модулей

Список литературы.

При написании книги автор в основном пользовался описанием Perl "Perl Programmers Reference Guide".

Наиболее известная зарубежная литература:

Programming Perl (the Camel Book)

Learning Perl (Llama Book)

[Назад] [Содержание]



Модули (packages).


Таблицы имен

Конструкторы и деструкторы

Классы

Создание библиотеки

Pragma библиотеки

Стандартные библиотеки

CPAN

В Perl реализован механизм модулей. Модуль это группа подпрограмм и переменных обычно включенных в один файл. Внутри одного модуля можно определить другой модуль. Начало модуля определяется директивой:

packages имя_модуля;

Конец модуля это конец блока или файла. Головной модуль имеет по умолчанию имя main. На имя внутри модуля можно ссылаться, добавляя '::' после имени модуля.

Например:

$main::var1 - переменная в головном модуле.

::var1 - то же самое. Имя main можно опускать.

$модуль1::var1 - переменная в модуле 'модуль1'

$модуль1::модуль2::var1 - Модуль2 содержится в модуле 1.

Только идентификаторы, начинающиеся с буквы или символа '_', хранятся в пространстве имен текущего модуля. Остальные хранятся в пространстве головного модуля main. Кроме этого имена STDIN, STDOUT, STDERR, ARGV, ARGVOUT, ENV, INC и SIG так же хранятся в головном модуле.

Таблицы имен.

Все имена модуля хранятся в ассоциативном массиве (хеше) с именем модуля, к которому добавлены символы "::". Таким образом имена головного модуля хранятся в %main:: , модуля 'mod1' в %mod1:: и т.д. Выражение вида *имя указывает значение элемента хеша 'имя', это удобно для определения констант.

Например:

*pi = \3.14159;

Здесь переменная $pi - это константа пи, которую уже нельзя изменить.

Конструкторы и деструкторы.

Конструктор - это подпрограмма, которая выполняется в момент создания объекта, а деструктор - удаления объекта. Для модуля это подпрограммы с именами BEGIN и END. При определении этих подпрограмм слово sub можно опускать.

Конструктор BEGIN выполняется сразу как только возможно, т.е. как только он определен, даже не завершая дальнейший разбор программы. Можно указать несколько блоков BEGIN. Они будут выполняться один за другим в порядке определения.

Деструктор END выполняется последним как только возможно, т.е. при завершении работы интерпретатора. Можно указать несколько блоков END, при этом они будут выполняться в обратном определению порядке.


Классы.

В Perl нет специального синтаксиса для классов. Но функционально полноценными классами могут быть модули. При этом подпрограммы модуля становятся методами, а с помощью массива @ISA можно реализовать механизм наследования в классах. Более подробно классы описаны отдельно.

Создание библиотеки.

Если вы хотите создать модуль отдельным файлом и использовать как библиотеку подпрограмм, при этом вызывать подпрограммы библиотеки, не указывая имени модуля, вам необходимо оформить модуль следующим образом:

package имя_модуля; # Такое же как и имя этого файла без расширения '.pm' require Exporter; # Обязательная строка для экспорта имен @ISA = qw(Exporter); # -//- @EXPORT = qw(func1 func2) # Перечисляем имена функций. Внимание ! нет запятой! @EXPORT_OK = qw( $переменная @массив ); # Указать публичные переменные, массивы и т.д. если необходимо { # Начало блока модуля ..... sub func1 ........ sub func2 ........ 1; }

Данный файл с расширением ".pm" должен храниться в одной из библиотечных директорий Perl. Они перечислены в массиве @INC, одна из них обычно "/usr/local/lib/perl/".

В головной программе вы указываете:

use имя_модуля;

и вам становятся доступны имена подпрограмм данного модуля.

Perl библиотеки.

Стандартный набор библиотек обычно поставляется с дистрибутивом Perl, они разделяются на pragma библиотеки (работают как директивы компилятору) и стандартные библиотеки.

Pragma библиотеки.

Данные библиотеки используют как:

use имя;

когда хотят включить действие и

no имя;

когда выключить.

В стандартный набор входят следующие pragma:

diagnostics

Включить режим расширенной диагностики.

integer

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

less

Режим минимальной загрузки компилятора.

overload

Режим переопределения операторов.

sigtrap

Режим слежения за прерываниями.

strict

Режим ограниченного использования "опасных" операторов.

subs

Режим обязательного декларирования подпрограмм.

Стандартные библиотеки.

AnyDBM_File

Возможность работы с разными типами баз данных.



AutoLoader

Загрузка в память функций только во время вызова.

AutoSplit

Разделить модуль для автозагрузки.

Benchmark

Анализ скорости исполнения программы.

Carp

Предупреждения об ошибках.

Config

Доступ к конфигурации Perl.

Cwd

Получить имя текущей рабочей директории.

DB_File

Работа с базой данных формата Berkley DB.

Devel::SelfStubber

Режим отладки автозагрузки.

DynaLoader

Динамическая загрузка библиотек C.

English

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

Env

Импортировать имена переменных окружения

Exporter

Обеспечивает экспорт/импорт для модулей.

ExtUtils::LibList

Определяет используемые библиотеки.

ExtUtils::MakeMaker

Создает файл проекта Makefile

ExtUtils::Manifest

Программы для создания и проверки файла MANIFEST

ExtUtils::Mkbootstrap

Применение файла начальной загрузки для DynaLoader.

Fcntl

Определения как и в С Fcntl.h

File::Basename

Синтаксический разбор спецификации файла.

File::CheckTree

Быстрый проход по директориям диска.

File::Find

Быстрый поиск файлов по директориям.

FileHandle

Обеспечивает объектный метод доступа к указателям файлов.

File::Path

Создание/удаление директорий.

Getopt::Long

Расширенная обработка опций.

Getopt::Std

Стандартная обработка опций.

I18N::Collate

Сравнение символов локальной кодировки.

IPC::Open2

Межпроцессорный обмен по чтению и записи.

IPC::Open3

Межпроцессорный обмен по чтению, записи, и обработки ошибок.

Net::Ping

Тест доступа к хосту.

POSIX

Стандартный интерфейс по IEEE Std 1003.1

SelfLoader

Загрузка функций только по вызову.

Socket

Определение структур и констант как и в С socket.h

Test::Harness

Стандартный тест с статистикой.

Text::Abbrev

Создание таблицы сокращений по списку.

Подробное описание каждой библиотеки записано в самом файле.

CPAN

Программисты всего мира, работающие с Perl, создали общедоступную библиотеку модулей CPAN. Она доступна через Интернет и содержит огромное количество различных по назначению модулей. К ним относятся документаторы, системные интерфейсы, интерфейсы работы с базами данных, работа в сети, с файлами, Интернет-броузеры, системы поиска, огромное количество CGI скриптов для Web серверов и многое-многое другое. Список некоторых CPAN серверов вы можете найти в приложении.

[Назад] [Содержание] [Вперед]


Name-win


==========================================

== Библиотека компьютерной документации ==

============ 'Roga и Копыта' =============

==========================================

============ www.roga.by.ru ==============

==========================================

Приходите и окунитесь в мир виртуальной

информации. - www.roga.by.ru

==========================================

==========================================

Название....................Жемчужные формы

Автор:.......С.Голубицкий, www.compuferra.ru

Издательство......................Нет данных

Изданно...........................Нет данных



Операторы и приоритеты.


Термы и левосторонние списковые операторы

Унарные операторы

Операторы "привязки" =~ и !=

Мультипликативные операторы

Аддитивные операторы

Операторы сдвига

Именованные унарные операторы

Операторы отношений

Операторы равенства

Операторы работы с битами

Логические операторы && (AND) и || (OR)

Оператор диапазона '..'

Условный оператор '?:'

Операторы присваивания

Оператор ',' (запятая)

Логические not, and, or, xor

Операторы ограничители строк

Операторы ввода-вывода

Слияние констант

Целочисленная арифметика

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

ассоц.

операторы

левая термы и левосторонние списковые операторы
левая ->
- ++ --
правая **
правая ! ~ \ унарные + и -
левая =~ !~
левая * / % x
левая + - .
левая << >>
- именованные унарные операторы
- < > <= >= lt gt le ge
- == != <=> eq ne cmp
левая &
левая | ^
левая &&
левая ||
- ..
правая ?:
правая = += -= *= и т.д.
левая , =>
- правосторонние списковые операторы
левая not
левая and
левая or xor

Термы и левосторонние списковые операторы.

Любой терм имеет самый высокий приоритет. К терму относятся переменные, кавычки и их операторы, арифметические и логические выражения в скобках, любые функции с параметрами в скобках. Фактически таких функций нет, так как это просто унарные и списковые операторы. Просто они ведут себя подобно функциям с параметрами в скобках. Подробно смотри главу Функции.

Если после любого спискового оператора ( print(), и т.д.) или унарного оператора (chdir(), и т.д.) следует левая круглая скобка, то операторы внутри скобок имеют наивысший приоритет. Так же как и обычные функции.

Если скобки отсутствуют, то приоритет списковых операторов или наивысший или наименьший в отношении операторов справа или слева от него.


Например:

@i = ('a ','b ', print 'c ', 'd '); print "\n",@i,"\n";

Результат:

c d a b 1

Здесь мы имеем списковый оператор print. Для запятых слева от него он имеет наименьший приоритет, но повышает приоритет правой запятой. Поэтому правая запятая воспринимается как параметр для print и печатается 'c d', а левая просто записывает код завершения операции в массив @i и последний print показывает это.

Оператор '->'

Так же как в С или С++ это инфиксный оператор переадресации. Если справа от него стоит [...] или {...} выражение, то правая часть может быть непосредственной или символической ссылкой на массив или хеш. В противном случае правая сторона это метод или простой скаляр, содержащий имя метода, а правая - или объект или имя класса. Подробно смотри главу Классы.

Операторы ++ (инкремент) и -- (декремент).

Эти операторы работают так же как и в С. Если оператор стоит перед переменной, то значение переменной изменяется на 1 и полученное значение используется. Если после переменной - то ее величина изменяется после применения.

Употребление инкремента к строковым переменным в Perl имеет одну особенность. Каждый символ остается в своем классе (большие, малые, цифры) и учитывается перенос предыдущего символа. Таким образом строковые переменные с цифрами работают как числовые переменные.

Пример:

print ++($i = "09"); # Результат "10"

print ++($i = "a9"); # "b0"

print ++($i = "az"); # "ba" print ++($i = "aZ"); # "bA"

Оператор ** (возведение в степень)

Пример:

print 4**2 # Результат 16

print -4**2 # Результат -16 т.е. -(4**2)

Унарные операторы.

'!' - логическое отрицание
'-' - арифметический минус
'~' - побитная инверсия (дополнение до 1)
'+' - арифметический плюс
'\' - получение ссылки на переменную (как & в С)
Операторы "привязки" =~ и != .

Эти "необычные", я бы даже сказал, оригинальные операторы имеют очень широкое применение в Perl. Можно даже назвать их "оригинальным" решением. Оператор =~ логически связывает левую часть выражения с патерном (pattern - образец, шаблон, модель) в правой. По умолчанию поиск или изменение по патерну выполняется в переменной $_ Операторы привязки позволяют делать это с любой переменной, указанной в левой части. Логическим результатом будет успех операции. Если в правой части вместо патерна присутствует выражение, то результат этого выражения воспринимается как патерн. Однако это не очень эффективно, т.к. патерн будет компилироваться во время исполнения программы, что заметно снизит быстродействие. Оператор != аналогичен =~, только результат совпадения инвертируется (логическое "нет"). Подробное применение этих операторов приводится в главе Патерны.



Мультипликативные операторы.

'*' - арифметическое умножение
'/' - арифметическое деление
'%' - арифметический модуль
'x' - оператор повторения
В скалярном контексте возвращает строку левой части, повторенную величиной, указанной в правой части. В списковом контексте, если в левой части список, то в круглых скобках - повторенный список.

Пример:



print '*' x 5; # Результат '*****'

print (1,2) x 3; # Результат 121212

Аддитивные операторы.

'+' - арифметический плюс
'-' - арифметический минус
'.' - конкатенация (объединение) строк
Операторы сдвига.

'<<' - Сдвигает побитно влево значение выражения в левой части
  на количество бит указанное в правой.
'>>' - Сдвигает побитно вправо значение выражения в левой части
  на количество бит указанное в правой.
Именованные унарные операторы.

Фактически это функции с одним аргументом. Круглые скобки можно опускать.

Операторы отношений.

'<' - арифметическое меньше
'>' - арифметическое больше
'<=' - арифметическое меньше или равно
'>=' - арифметическое больше или равно
'lt' - строковое меньше
'gt' - строковое больше
'le' - строковое меньше или равно
'ge' - строковое больше или равно
Операторы равенства.

'==' результат true если левая часть равна правой (равно)
'!=' - не равно
'<=>' - -1 если левая часть меньше правой, 0 если равна,
  1 если больше.
'eq' - строковое равно
'ne' - строковое не равно
'cmp' - как и '<=>' применительно к строкам
Операторы работы с битами.

'&' - побитное AND
'|' - побитное OR
'^' - побитное XOR
Логические операторы && (AND) и || (OR).

'&&' - если левое выражение возвращает false, правое не выполняется.
'||' - если левое выражение возвращает true, правое не выполняется.
Отличие от подобных операторов в С заключается в том, что в С возвращаемое значение либо 0, либо 1, тогда как в Perl возвращается результат выражения.



Оператор диапазона '..'

Результат работы данного оператора зависит от контекста. В списковом контексте результат есть список с элементами, первый элемент которого это левое выражение и последнее - правое. Значение каждого элемента внутри списка увеличивается на 1. Данный оператор удобен для небольших циклов, т.к. память отводится для всего списка целиком. Поэтому будьте внимательны и не задавайте слишком большой диапазон.

Пример:

for $i (1..4) { print "$i "; }

Результат: 1 2 3 4

В скалярном контексте результат - логическое значение. Каждая '..' операция устанавливает свое собственное состояние. Это false до тех пор пока левый операнд false. Как только левый операнд стал true результат - true до тех пока правый true, после чего результат опять - false. Если вы не хотите проверять правый операнд, то используйте оператор '...'.

Правый операнд не вычисляется пока результат false и левый операнд не вычисляется пока результат true. Приоритетность оператора '..' немного ниже чем '&&' и '||'. Возвращаемое значение если flase - нулевая строка, если true - порядковый номер начиная с 1. Порядковый номер обнуляется для каждого нового диапазона. Последний порядковый номер добавляется строкой "E0" которая не изменяет его значение, но позволяет фиксировать последнее значение.

Пример:

@алфавит = ('a'..'z'); # Массив малых букв латинского алфавита

@цифры = (0..9); # Массив цифр

Условный оператор '?:'

Этот оператор работает так же как и в С. Если выражение перед '?' истинно, то выполняется аргумент перед ':' - иначе после ':'.

Пример:

$i = 1; $i > 1 ? print "больше" : print "меньше";

Результат: меньше

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

'=' - обычный оператор "присвоить" правое значение переменной слева
Вся эта группа операторов подобна операторам С, т.е.



$i += 2;

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



$i = $i + 2;

Остальные операторы этой группы работают аналогично. Допустимы следующие операторы:

**=
+=, -=, .=
*=, /=, %=, x=
&=, |=, ^=
<<=, >>=
&&=, ||=
<


Приоритет всей этой группы операторов равен приоритету '='.

Оператор ',' (запятая)

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

Операторы not, and, or, xor

Оператор логическое not (отрицание).

Унарный not возвращает противоположное значение, полученное выражением справа. Он эквивалентен '!', но имеет очень низкий приоритет.

Оператор логическое and (И).

Выполняет логическую конъюнкцию двух выражений. Эквивалентен '&&', но имеет очень низкий приоритет и "краткость" действия, т. е. если левое выражение равно false - левое не выполняется.

Логическое or (ИЛИ).

Выполняет логическую дизъюнкцию двух выражений. Эквивалентен '||', но имеет очень низкий приоритет и "краткость" действия, т. е. если левое выражение равно true - левое не выполняется.

Логическое xor (исключающее ИЛИ).

Выполняет логическое исключающие или. Всегда выполняются оба правое и левое выражение.

В Perl отсутствуют операторы языка С такие как:

унарное & - получить адрес. Для этого применяется '\'.
унарный * - переадресация.
(TYPE) - совмещение типов.
Операторы ограничители строк.

Обычно ограничителями строк мы считаем литералы, но в Perl это операторы выполняющие разного рода интерполяцию и поиск по шаблону. Вы можете сами задавать удобные для вас ограничители. В следующей таблице приведен полный перечень вариантов. Фигурные скобки '{}' обозначают любой символ, используемый для ограничителя. В случае использования скобок (круглых '()', квадратных '[]', фигурных '{}', угловых '<>') в начале ставится открывающаяся скобка, а в конце закрывающая.

По умолчанию

Полное

Функция

Интерполяция

'' q{} Literal нет
"" qq{} Литерал да
`` qx{} Команда да
  qw{} Список слов нет
// m{} Шаблон да
  s{}{} Подстановка да
  tr{}{} Трансляция нет
<


В строках допускающих интерполяцию имена переменных, начинающиеся с символов '$' или '@' - интерполируются, т.е. в строку вставляется значение строки или массива. Данные последовательности символов имеют специальное значение:

\t символ табуляции
\n символ новой строки
\r возврат
\f перевод формата
\v вертикальная табуляция
\b backspace (забой)
\a звонок
\e escape
\034 восьмеричный символ
\x1a шестнадцатеричный символ
\c[ символ управления
\l нижний регистр следующего символа
\u верхний регистр следующего символа
\L нижний регистр для всех символов до \E
\U верхний регистр для всех символов до \E
\E ограничитель смены регистра
\Q отмена действия метасимволов до \E
Шаблоны интерполируются как регулярные выражения. Это выполняется вторым проходом после интерполяции переменных, поэтому в шаблоны можно вставлять переменные. Для отмены интерполяции используйте '\Q'. Если вы применяете вложенные ограничители, то внутренние ограничители работать не будут.

?PATERN?

Действие этого оператора аналогично /шаблон/, но выполняется до первого совпадения. Это удобно для поиска наличия какой-нибудь строки в одном или множестве файлов. Это не очень удачный оператор, поэтому в следующих версиях Perl его возможно не будет.

m/PATERN/gimosx

/PATERN/gimosx

Поиск в строке по патерну (шаблону). В скалярном контексте возвращает логическое значение true (1) или false (''). Если строка не указана с помощью операторов '=~' или '!~', поиск ведется в строке $_ Опции:

g - Глобальный поиск. Поиск всех вхождений.
i - Сравнение не зависит от регистра (верхний или нижний)
m - Строка многострочная.
o - однопроходная компиляция
s - однострочная строка
x - используются расширенные регулярные выражения.
Если '/' - ограничитель, то начальное 'm' можно опустить. С помощью него в качестве ограничителя может быть любой символ кроме пробела.

PATTERN может содержать переменные, которые будут интерполироваться (перекомпилироваться) каждый раз в момент вычисления. Переменные $) и $| не интерполируются. Если вы хотите, что бы такой шаблон интерполировался один раз - добавьте /o. Это необходимо делать в циклах поиска для увеличения быстродействия, однако, если вы измените значение переменной, Perl этого даже не заметит.



Если PATERN - нулевая строка, то используется последнее регулярное выражение.

В скалярном контексте возвращается список элементы которого - результаты выполнения выражений в скобках патерна ($1, $2, $3...). Обратите внимание что первый элемент $1.

Пример:



$a = "/usr/local/perl/perl.bin"; # Анализируемая строка

Цель: Создать массив @dirs с именами директорий.

Решение: Самый простой способ воспользоваться split('\/') но в качестве примера используем скобки.



@dirs =~ m[/(\w*)/(\w*)/(\w*)/(\w*)]

Здесь 'm[' - использовать квадратные скобки как ограничители. (\w*)- шаблон алфавитно-цифровой последовательности.

В результате @dirs равен ('usr', 'local', 'perl')

q/строка/

'строка'

Строка литералов. Не интерполируется. Внутри строки разрешается использовать \' или \\ для обозначения символов ' и \ .

Пример:

print q#Привет.#; # Результат Привет.

print 'O\'K'; # O'K

qq/строка/

"строка"

Интерполируемая строка.

Пример:

$var = 13; print "\$var = $var";

Результат: $var = 13

qx/строка/

`строка`

Сначала строка интерполируется, а потом выполняется как системная команда.

Пример:

print `date`;

Результат: Thu Nov 14 13:36:49 MSK 1996

qw/строка/

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

Пример:

print qw/Построимся и спасемся!/; # ('Построимся','и','спасемся!')

Результат:

Построимсяиспасемся!

Часто применяется как:

use POSIX qw( setlocale localeconv ) @EXPORT = qw( proc1 var );

s/шаблон/подстрока/egimosx

Поиск по шаблону и в случае успеха замена подстрокой. Возвращает количество произведенных подстановок, иначе false (0). Если строка в которой ведется поиск не указана (операторы =~ или != ), то используется переменная $_ . Если в качестве разделителя '/' использовать одинарную кавычку ('), то интерполяции не будет, иначе можно применять переменные в шаблоне или подстроке.

Опции:

e - Рассматривать правую часть как выражение.
g - Глобальный поиск.
i - Без различия регистра букв
m - многострочная переменная
o - компилировать шаблон один раз
s - однострочная переменная
x - расширенное регулярное выражение
<


Разделитель '/' можно заменить на любой алфавитно-цифровой символ кроме пробела.

Пример:



$var = "12345"; # исходная строка $var =~ s/1/0/; # Заменить '1' на '0'. Результат 02345 $var =~ s(5)(.); # Заменить '5' на '.' Результат 0234.

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



$var =~ s/\d*/каламбур/; Заменить все цифры. Результат 'каламбур.'

$var =~ s/а/о/g; # Заменить все 'а' на 'о'. Результат 'коломбур.'

$var = "12 34"; # Новое значение

$var =~ s/(\d\d) (\d\d)/$2 $1/; # Поменять местами числа. Результат '34 12'.

tr/таблица1/таблица2/cds

y/таблица1/таблица2/cds

Замена всех символов из "таблица1" на соответствующий символ из "таблица2". Результат - количество замен или стираний. Без оператора =~ или != операция выполняется со строкой $_. Для совместимости с программой sed вместо tr можно писать 'y'.

Опции:

c - дополнение "таблица1"
d - стереть найденные, но не замененные символы.
s - "сжать" повторяющиеся замененные символы.
Если указана опция /d таблица2 всегда интерпретируется как положено. Другими словами, если таблица2 короче, чем таблица1, то символ из таблицы1 интерпретируется всегда. Если таблица2 - null, то все символы строки остаются неизменными. Это удобно для подсчета количества символов в строке определенного класса или для сжатия повторяющихся символов, например, пробелов.

Пример:



$s = "hello"; # Исходная строка

$s =~ tr/a-z/A-Z/; # Заменить малые буквы на большие. Результат # 'HELLO'

$s = 'Hel....lo'; $s =~ tr/a-zA-z/_/c; # Заменить все не буквы на '_' # Результат 'Hel____lo' $s =~ tr/_/ /s; # Заменить '_' на ' ' и сжать. # Результат 'Hel lo' $s =~ tr/a-zA-Z /a-zA-Z/d; # Удалить все не буквы. Результат 'Hello'

Если один и тот же символ несколько раз указан в таблице1, то применяется только первая замена.

Операторы ввода-вывода.

В Perl существует несколько операторов ввода-вывода. Первый это скобки из символа '`' - акцента. Строка в этих скобках воспринимается как системная команда и результат ее действия возвращается как "псевдо" литерал. В скалярном контексте это строка содержащая весь результат, а в списковом - список, элементы которого - строки результата. Статус выполненной команды хранится в переменной $? .



Следующая команда ввода вывода выглядит как '<файл>'. Вычисление <файл> приводит к чтению строки из файла. Обратите внимание, что 'файл' здесь не имя файла, а указатель файла, который создается функцией open(). В скалярном контексте читается одна строка вместе с символом '\n' - перевода строки, а в списковом весь файл читается в список, элементы которого суть строки файла. В случае обнаружения конца файла результат оператора не определен и воспринимается как false. Если не указана переменная результата, то по умолчанию это $_. Указатель файла по умолчанию STDIN - стандартный ввод.

Пример:

while(<>) { print; }; # Прочитать и вывести весь файл STDIN

У оператора '<>' есть одна отличительная особенность. Если в командной строке нет никаких аргументов, то читается стандартный ввод, если есть аргументы, то они считаются именами файлов, которые последовательно читаются.

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

Пример:

while(<*.pl>) { print;}; # То же что и ls *.pl

@files = <*>; # Массив @files содержит имена файлов в директории

но лучше сделать: @files = glob("*"); т.к. внутри скобок можно использовать переменные.

Слияние констант.

Как и С Perl выполняет возможные вычисления в период компиляции. Так подстановка символов после '\' , операция конкатенации строк, арифметические выражения, содержащие только одни константы, все это делается в момент компиляции, что существенно увеличивает скорость выполнения программы.

Целочисленная арифметика.

По умолчанию Perl выполняет арифметику с плавающей запятой, но если вы укажете:

use integer;

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

no integer;

[Назад] [Содержание] [Вперед]


От простого к сложному


Прежде чем приступить к последовательному ознакомлению с не знакомым для вас языком, должен оговориться и сказать, что все примеры да и сам язык описанию которого посвящена эта книга это Perl версии 5.003 для операционной системы FreeBSD версии 2.01. Существуют реализации этого языка для операционных систем OS/2 , MS-DOS и Windows NT но они немного отстают по возможностям от оригинала, рожденного в недрах Unix.

Пример 1.

Введите в файл test1.pl следующие строки:

#!/usr/local/bin/perl # Содержимое файла test1.pl print "Наше Вам с кисточкой!\n";

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

#!/usr/local/bin/perl

Данная строка должна быть первой в любой Perl-программе. Она указывает системному интерпретатору что данный файл - это Perl-программа.

# Содержимое файла test1.pl

Эта строка называется комментарием. Она всегда начинается символом '#' и заканчивается таким объяснением что как говорил великий Ходжа Насреддин "это тонкий философский вопрос", а говоря простым языком здесь можно писать все что угодно. Даже пожелание руководству. Уж здесь оно точно до него не дойдет.

print "Наше Вам с кисточкой!\n";

Самая последняя ну и конечно главная. Она просто выводит на экран надпись "Наше Вам с кисточкой!".

Здесь слово print - это команда "вывести". Все что в кавычках - это символы, \n - перевод строки и ';' - признак конца команды. Он обязателен. В одной строке может быть несколько команд и все они должны завершаться символом ';'. После него может быть символ '#' - это значит остаток строки считается комментарием.

Над этой строкой автору пришлось больше всего поломать голову так как в нее постоянно лезли какие то странные "hello", "hello all", "Построимся и спасемся", "Строй наше спасение" и т. д. и т.п.

Если вы никогда не работали с Perl, то бьюсь на спор в 10$, что данная программа сразу у вас не заработает! Не потому что она не верна, а потому что "Нельзя объять необъятное". Сразу, потом можно, да и то частями. Сначала сделайте ваш файл test1.pl исполняемым. Для этого введите команду:


chmod +x test1.pl

Затем проверьте где у вас Perl. Для этого введите:

which perl

Система вам выдаст что то вроде: /usr/bin/perl

Если:

perl: Command not found.

То тогда закройте книжку и ложитесь спать. У вас просто нет Perl или он не установлен. А мне остается послать вас к системному администратору или к man (для переводчиков- man сокращение от manual а не то что вы подумали).

Теперь проверьте что бы строка 01 содержала то что выдала команда which. Если совпало то введите:

test1.pl

и бьюсь на 50$, что и теперь программа не заработает, так как правильней ввести:

./test1.pl

Если я проиграл, то не радуйтесь. Да же если вам удалось запустить программу как test1.pl это значит, что у вас будут неприятности в будущем.

Пример 2.

Данная программа выводит на экран все ваши секреты. А именно файл /etc/passwd.

#!/usr/local/bin/perl open(PASS, "</etc/passwd") || die "Файл не найден!"; while(<PASS>) { print; } close(PASS);

Пояснения:

open(PASS, "</etc/passwd") || die "Файл не найден!";

"Открыть" файл, т.е. создать указатель файла PASS, и в случае ошибки выдать "Файл не найден!" и закончить программу.

while(<PASS>)

Читать по одной строке файла в переменную по умолчанию $_.

{

Открыть блок операторов.

print;

Вывести на экран переменную по умолчанию $_

}

Конец блока.

close(PASS);

Закрыть файл. Этого можно и не делать, т. к. файл автоматически закроется после окончания программы.

Результат работы этой программы тот же что и команды cat /etc/passwd. По экрану пробежали непонятные строки но зато теперь перед вами открыты горизонты Perl программирования! Все последующие примеры будут развитием этой программы и она превратится из гадкого утенка в прекрасного лебедя (не генерала).

Пример 3.

Разделение полей.

#!/usr/local/bin/perl open(PASS, "</etc/passwd") || die "Файл не найден!"; while(&ltPASS>) { ($login, $pass, $uid, $gid, $name, $home_dir, $shell) = split(':'); print "$login \t $name\n"; } close(PASS);



Пояснение:

($login, $pass, $uid, $gid, $name, $home_dir, $shell) = split(':');

Присвоить указанным переменным поля входной строки, считая разделителем символ ':'.

print "$login \t $name\n";

Вывести login - имя пользователя и его описание. Поля разделены символом '\t' - табуляции.

Пример 4.

Вывести имена пользователей, отсортированных по группам.

#!/usr/local/bin/perl open(PASS, "sort -n -t : +3 -4 +0 /etc/passwd|") || die "Файл не найден!"; while(<PASS>) { ($login, $pass, $uid, $gid, $name, $home_dir, $shell) = split(':'); print "$login \t $gid \t $name\n"; } close(PASS);

Пояснения:

open(PASS, "sort -n -t : +3 -4 +0 /etc/passwd|") || die "Файл не найден!";

В данной строке весь фокус! Входным файлом для нашей программы стал выход команды sort которая и отсортирует входные данные.

Форматированный вывод.

Ну а теперь напечатаем на экране все наши данные в удобной форме.

#!/usr/local/bin/perl

open(PASS, "sort -n -t : +3 -4 +0 /etc/passwd|") || die "Файл не найден!"; while(<PASS>) { ($login, $pass, $uid, $gid, $name, $home_dir, $shell) = split(':'); write(); # Форматированный вывод данных. } close(PASS); exit 0; # Завершение программы

############ Описание формы вывода ##################

format STDOUT =

Пользователь: ^

Фрагмент результата:

Пользователь: Калужский ликероводочный завод. Лучшие водки и настойки. Звонить только перед праздником Кострикову Анатолию т. 2-23-06,,, ---------------------------------------------------------------------- Login:uucryst Uid:1055 Gid:66 Home dir:/var/spool/uucppublic/ ----------------------------------------------------------------------

Пользователь: Торговый Дом Дилен,,,

---------------------------------------------------------------------- Login:uudilen Uid:1075 Gid:66 Home dir:/var/spool/uucppublic ----------------------------------------------------------------------

Если вам интересно узнать как работает эта программа, то переверните страницу и начините свое путешествие в мире Perl. Желаю удачи!

[Содержание] [Вперед]


Отладка Perl программ.


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

Команды отладчика.

h - Получить справку по командам.

T - Просмотреть стек программы

s - Выполнить одну команду и остановиться.

n - Выполнить подпрограмму и остановиться.

r - Выполнить текущую подпрограмму и остановиться.

c - Продолжить выполнение до следующей точки остановки.

c номер - Продолжить выполнение до строки с данным номером.

- Повторить последнюю команду n или s.

l min+incr - Вывести incr+1 строк программы начиная со строки min.

l min-max - Вывести строки начиная с min до max.

l номер - Вывести строку с указанным номером.

l - Вывести следующий экран строк.

- - Вывести предыдущий экран строк.

w строк - Вывести экран строк. Текущая в середине.

l подпрограмма - Вывести строки указанной подпрограммы.

/шаблон/ - Найти строку в тексте программы.

?шаблон? - Обратный поиск строки в тексте программы.

L - Вывести строки с точками останова и активами.

S - Вывести имена всех подпрограмм.

t - Включить или выключить трассировку.

b строка [ условие] - Установить точку остановки.

b подпрограмма [ условие ] - Установить точку остановки в начале указанной подпрограммы и если указано при данном условии.

d - Убрать точку остановки.

D - Убрать все точки остановки.

a строка команда - Установить актив (команду которая выполнится вместе с указанной строкой. "команда" - обычная команда Perl.

A - Стереть все активы.

- Выполнять команду перед каждой остановкой.

> команда - Выполнить команду после остановки отладчика.

V модуль [имена] - Вывести значение всех или указанных имен в модуле. Внимание! Символ '$' не вводится.

X [имена] - То же что и V , но только для текущего модуля.

! номер - Выполнить одну строку программы.

! -номер - Выполнить одну команду с номером предшествующим текущей строке.

H - n - Вывести n последних выполненных команд.

q или ^D - Выход из программы.

команда - Выполнить команду Perl.

p выражение - Вывести значение выражения.

Конструктор BEGIN не отслеживается отладчиком, но можно в теле конструктора указать:

$DB::single =1;

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

[Назад] [Содержание] [Вперед]



Переменные.


Контекст

Скалярные значения

Конструкторы скаляров

Конструкторы списков

Тип typeglobs

В Perl существует три типа структур данных: скаляры, массивы скаляров и хеши (hashes) - ассоциативные массивы скаляров. Обычно элементы массивов индексируются целыми числами, первый элемент - нулевой. Отрицательное значение индекса обозначает номер позиции элемента с конца. Хеши индексируются строками символов.

Имена скалярных переменных всегда начинаются с символа '$' даже когда обозначают элемент массива.

Пример:

$var1 # Простой скаляр 'var1'

$var1[0] # Первый элемент массива 'var1'

$var1{'first'} # Элемент с индексом 'first'

В случае использования имени массива "целиком" или его "среза" перед именем массива ставится символ '@'.

Пример:

@var1 # Все элементы массива var1 ( $var1[0], $var1[1], ... $var1[n])

@var1[1,3,10] # Элементы $var1[1], $var1[3], $var1[10]

@var1{'first','last'} # то же что и ( $var1{'first'}, $var1{'last'} )

Хеш "целиком" начинается с символа '%'.

Пример:

%var, %key, %years

Имена подпрограмм начинаются символом '&', если из контекста не видно, что это подпрограмма.

Пример:

&sub1, &test_prog, test(12)

Имена таблиц символов всегда начинаются символом '*'.

Каждый тип переменных имеет свою область памяти поэтому $var1 и $var1[0] совершенно разные переменные, хотя $var1[0] часть массива @var1. Так же @var1 и %var1 - разные массивы переменных.

Имена переменных могут содержать любые буквенно-цифровые символы за исключением пробела и табуляции. Эти символы используются в качестве разделителей. Большие и малые буквы различаются поэтому $var1 и $Var1 - разные переменные. В Perl по умолчанию имена меток и указателей файлов пишут большими буквами.

Контекст.

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


Пример:

$var1 = <>; # Прочитать одну строку файла

@var1 = <>; # Прочитать все строки файла в массив @var1

$var1 = (1,2,3); # $var = 3 - количество элементов

@var1 = (1,2,3); # Создание массива @var1 с элементами 1,2,3

Скалярные значения.

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

В Perl не существует типов "строка" или "число" или "файл" или что-то еще. Это контекстно зависимый полиморфный язык для работы с текстами.

Скаляр имеет логическое значение "TRUE" (истина), если это не нулевая строка или число не равное 0.

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

Количество элементов массива так же является скаляром и начинается символами $# подобно интерпретатору csh. Фактически $#var1 - это индекс последнего элемента массива. Нужно помнить, что первый элемент имеет индекс 0, поэтому количество элементов определяется как $#var1+1 . Присвоение значения $#var1 изменит длину массива и разрушит "оставленные" значения. Присвоение значения элементу массива с индексом больше чем $#var1 увеличит размер массива, а присвоение ему нулевого списка -обнулит.

В скалярном контексте имя массива возвращает его длину (для списка возвращается последний элемент).

Пример:

@var1 = (4, 3, 2, 1); # Присвоение значения элементам массива $i = @var1; # Использование скалярного контекста print $i; # Печать результата 4 - кол-во элементов print @var1; # Списковый контекст, печать всех элементов.



Для принудительного получения скалярного значения удобно применять функцию scalar().

Пример:

print scalar(@var1); # Вывод длины массива а не его значений

Хеш в скалярном контексте возвращает "true", если существует хотя бы одна пара "ключ-значение". Фактически возвращается строка типа 2/8 где 8 - количество выделенных "ячеек" памяти, а 2 - количество использованных.

Конструкторы скаляров.

Числа пишутся стандартно:

123 123.123 0.12 .12E-10 0xABCD # Шестнадцатиричная запись 0377 # Если 0 в начале - восьмеричная 123_456_123 # Так тоже можно для удобства чтения.

Строки ограничиваются одинарными (') или двойными (") кавычками:

'Равняйсь, смирно!' "Построимся и спасемся."

Способов обозначения строк очень много. Смотрите описание оператора qq.

В хеше можно опускать кавычки, если индекс не содержит пробелов.

Пример:

$var1{first} то же что и $var1{'first'}

Обратите внимание на то, что перед первой одинарной кавычкой должен стоять пробел, иначе строка воспримется как имя переменной, т. к. в именах разрешено использование одинарных кавычек. Запрещается в кавычках применять зарезервированные литералы __LINE__ (номер текущей строки программы), __FILE__ (текущий файл). Для обозначения конца программы можно применять литерал __END__ Весь последующий текст игнорируется, но его можно прочитать используя указатель файла DATA.

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

В Perl есть возможность вставлять текст документа прямо в программу. Так называемый "here-doc" (здесь текст) метод. Обозначается символами << за которыми идет слово-ограничитель.

Пример:

print <<EOF; # Все строки до EOF - текст для печати.

Эй вы трое, идите двое сюда! Что стоишь! Я тебе говорю!!

Полковник Савонькин. EOF

Конструкторы списков.



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

Пример:

@var1 = (1, 2, 'привет', 1.2); # Присвоить значение элементам.

где

$var1[0] = 1,

$var1[1] = 2,

$var1[2] = 'привет'

$var1[3] = 1.2

$var1 = (1, 2, 'привет', 1.2);

а здесь $var1 = 1.2 т.е. последнее значение списка.

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

Пример:

@s1 = (1, 2, 3); # Первый список

@s2 = (6, 7, 8); # Второй

@s = (0, @s1, 4, 5, @s2, 9, 10); # Включаем списки @s1 и @s2

print @s; # Результат: 012345678910 - значения без пробелов.

Список без элементов обозначается как () и называется нуль-списком. Списковое выражение можно употреблять как имя массива, но при этом его нужно брать в круглые скобки.

Пример:

print ('январь','февраль','март')[1];

Результат: февраль

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

Пример:

($a, $b, $c) = (1, 2, 3); # $a = 1, $b = 2, $c = 3

Присваивание списков в скалярном контексте возвращает количество присвоенных элементов.

Пример:

$x = (($a, $b, $c) = (1,2)); # Результат $x=2

В случае присваивания списка хешу, список рассматривается как пары: ключ-значение.

Пример:

%дни_месяца = ('январь', 31, 'февраль', 30);

Результат: $дни_месяца{январь} = 31, $дни_месяца{февраль} = 30

Для удобства записи можно использовать выражение с => .

Пример:

%дни_месяца = ( январь => 31, февраль => 30, );

Тип typeglobs

В Perl используется специальный внутренний тип typeglog для записи массива всех переменных. Такие массивы начинаются с символа '*'. Их удобно применять для передачи ссылок на массивы и хеши, но в данной версии Perl уже есть возможность применять ссылки, поэтому это делается очень редко. Единственно где это необходимо, так это для работы со ссылками на файлы. Например, если вам нужно создать локальную ссылку на файл в процедуре, то это лучше сделать так:

sub new_sub { local *IN; # Ссылка на файл open (IN, "test") || return undef; # Открыть файл. Возврат при ошибке. ......... return; }

Более подробно это описано в главе Ссылки.

[Назад] [Содержание] [Вперед]


Подпрограммы.


Private переменные

Переменные типа local

Прототипы (prototypes)

Ссылка как параметр

Переопределение встроенных функций

Автозагрузка

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

sub имя; - Только декларация. Определение ниже.

sub имя (прототипы); - То же но с декларацией параметров.

sub имя блок; - Декларация и определение.

sub имя (прототипы) блок; - То же, но с параметрами.

Для определения динамической анонимной подпрограммы можно указать:

$переменная = sub блок;

Для импортирования подпрограмм из других модулей используйте:

use модуль qw(подпрограмма1 подпрограмма2 );

Вызов подпрограммы:

имя(список параметров); # символ '&' можно не указывать. имя список; # Если подпрограмма уже декларирована. &имя; # Параметры в @_

Все параметры передаются подпрограмме как массив @_. Соответственно $_[0] - первый параметр, $_[1] - второй и т.д. Массив @_ - локальный, но он содержит адреса параметров, поэтому можно изменять значение параметров. Возвращаемое значение подпрограммы - результат последнего оператора. Это может быть как скаляр так и массив. Можно принудительно возвращать результат используя функцию return().

Подпрограмму можно вызвать, используя префикс '&' перед именем подпрограммы. Если подпрограмма предварительно продекларирована, то префикс и скобки можно опустить.

Private переменные.

Для применения переменных доступных только внутри блока или подпрограммы необходимо определить их с помощью функции my(список).

Если переменная одна, то скобки можно опустить.

my() декларирует private переменные в пределах текущей подпрограммы, блока, функции eval() или do/require/use файлов. Private переменные аналогичны auto переменным в С.

Пример:

# Программа вычисления факториала.

print fact(3); # вычислить факториал 3*2*1

sub fact # Определяем подпрограмму. { my $m; # private переменная но не local ! $m = $_[0]; return 1 if $m


Можно указывать начальные значения private переменных как:

my(список) = выражение;

Так для вышеприведенного примера лучше было написать:

my($m) = $_[0];

Переменные типа local.

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

Прототипы (prototypes).

Для краткого описания типа передаваемых подпрограмме параметров можно применять прототипы. В Perl существуют следующие прототипы:

Декларация

Пример вызова

sub mylink($$) mylink $old, $new
sub myvec($$$) myvec $var, $offset, 1
sub myindex($$;$) myindex &getstring, "substr"
sub myreverse(@) myreverse $a, $b, $c
sub myjoin($@) myjoin ":",$a,$b,$c
sub mypop(\@) mypop @array
sub mysplice(\@$$@) mysplice @array, @array, 0, @pushme
sub mykeys(\%) mykeys %{$hashref}
sub myopen(*;$) myopen HANDLE, $name
sub mypipe(**) mypipe READHANDLE, WRITEHANDLE
sub mygrep(&@) mygrep { /foo/ } $a, $b, $c
sub myrand($) myrand 42
sub mytime() mytime
Здесь:

\'символ' - параметр с типом 'символ'

'@' или '%' - все оставшиеся параметры как список

'$' - скаляр

'&' - безымянная подпрограмма

'*' - ссылка на таблицу имен

';' - разграничитель обязательных и не обязательных параметров.

Ссылка как параметр.

Иногда нужно в качестве параметра передать подпрограмме не значение элемента массива, а ссылку на него, чтобы подпрограмма могла изменить значение элемента. Для этого в Perl к имени переменной добавляется символ '*' Подобное выражение называют 'type glob' так же как в Unix символом '*' обозначают "все возможные значения". Поэтому '*' для массива означает "все элементы массива". Для скаляров употреблять '*' не имеет смысла, т.к. они и так передаются ссылкой и вы можете изменять значение параметра, изменяя, например, переменную $_[0].

Переопределение встроенных функций.

Большинство встроенных функций Perl можно переопределить своими собственными. Обычно это делают для удобства совместимости Perl для разных платформ систем.

Для этого нужно перечислить имена этих функций в виде:

use subs 'функция1', 'функция2' ....;

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

Автозагрузка.

Если вы попытаетесь вызвать несуществующую функцию, то Perl немедленно выдаст сообщение об ошибке. Но если вы определите подпрограмму с именем 'AUTOLOAD', то она будет вызвана с теми же параметрами, а переменная $AUTOLOAD будет содержать имя несуществующей подпрограммы. Данный механизм очень удобен для средств отладки.

[Назад] [Содержание] [Вперед]


Регулярные выражения (шаблоны).


В данной главе описывается синтаксис регулярных выражений. Чаще всего в Perl они используются в операторах поиска и замены таких как s//, m/, операторах связки =~

или != и т.д. Как правило все эти операторы имеют схожие опции такие как:

i - не различать строчные и заглавные буквы.
m - считать строку многострочной.
s - однострочная строка.
x - расширенный синтаксис ( использование пробелов и комментариев)

Обычно все эти опции обозначают как '/x'. Их можно использовать даже внутри шаблонов, используя новую конструкцию (?...)

Регулярные выражения или шаблоны (pattern) то же самое, что и regexp процедуры в Unix. Выражения и синтаксис заимствованы из свободно распространяемых процедур V8 Генри Спенсера (Henry Spencer), там же они подробно и описаны.

В шаблонах используются следующие метасимволы (символы обозначающие группы других символов) часто называемые egrep - стандартом:

\ - считать следующий метасимвол как обычный символ.
^ - начало строки
. - один произвольный символ. Кроме '\n' - конец строки.
$ - конец строки
| - альтернатива (или)
() - группировка
[] - класс символов

Метасимволы имеют модификаторы (пишутся после метасимвола):

* - повторяется 0 или большее число раз
+ - -//- 1 или большее число раз
? - 1 или 0 раз
{n} - точно n раз
{n,} - по меньшей мере раз
{n,m} - не меньше n, но и не больше m

Во все других случаях фигурные скобки считаются обычными (регулярными) символами. Таким образом '*' эквивалентна {0,} , '+' - {1,} и '?' - {0,1}. n и m не могут быть больше 65536.

По умолчанию действие метасимволов "жадно" (greedy). Совпадение распространяется столько раз, сколько возможно, не учитывая результат действия следующих метасимволов. Если вы хотите "уменьшить их аппетит", то используйте символ '?'. Это не изменяет значение метасимволов, просто уменьшает распространение. Таким образом:

*? - станет 0 и более
+? - 1 и более
?? - 0 или 1 раз
{n}? - точно n раз
{n,}? - не меньше n раз
{n,m}? - больше или равно n и меньше m раз
<
Шаблоны работают так же, как и двойные кавычки, поэтому в них можно использовать `\` - символы (бэкслэш-символы):

\t - символ табуляции
\n - новая строка
\r - перевод каретки
- перевод формата
\v - вертикальная табуляция
\a - звонок
\e - escape
\033 - восьмеричная запись символа
\x1A - шестнадцатеричная
\c[ - control символ
\l - нижний регистр следующего символа
\u - верхний регистр -//-
\L - все символы в нижнем регистре до \E
\U - в верхнем -//-
\E - ограничитель смены регистра
\Q - отмена действия как метасимвола
Дополнительно в Perl добавлены следующие метасимволы:

\w - алфавитно-цифровой или '_' символ
\W - не -//-
\s - один пробел
\S - один не пробел
\d - одна цифра
\D - одна не цифра
Обратите внимание, что все это "один" символ. Для обозначения последовательности применяйте модификаторы. Так:

\w+ - слово
\d+ - целое число
[+-]?\d+ - целое со знаком
[+-]?\d+\.?\d* - число с точкой
Кроме того существуют мнимые метасимволы. Обозначающие не существующие символы в месте смены значения. Такие как:

\b - граница слова
\B - не граница слова
\A - начало строки
\Z - конец строки
\G - конец действия m//g
Граница слова (\b) - это мнимая точка между символами \w и \W. Внутри класса символов '\b' обозначает символ backspace (стирания). Метасимволы \A и \Z - аналогичны '^' и '$', но если начало строки '^' и конец строки '$' действуют для каждой строки в многострочной строке, то \A и \Z

обозначают начало и конец всей многострочной строки.

Если внутри шаблона применяется группировка (круглые скобки), то номер подстроки группы обозначается как '\цифра'. Заметьте, что за шаблоном в пределах выражения или блока эти группы обозначаются как '$цифра'. Кроме этого существуют дополнительные переменные:

$+ - обозначает последнее совпадение
$& - все совпадение
$` - все до совпадения
$' - все после совпадения
Пример:



$s = "Один 1 два 2 и три 3"; if ($s =~ /(\d+)\D+(\d+)/) { print "$1\n";# Результат '1' print "$2\n";# '2' print "$+\n";# '2' print "$&\n";# '1 два 2' print "$`\n";# 'Один ' print "$'\n";# ' и три 3' }



Perl версии 5 содержит дополнительные конструкции шаблонов:

(?#комментарий) - комментарий в теле шаблона.
(?:шаблон) - группировка как и '( )', но без обратной ссылки
(?=шаблон) - "заглядывание" вперед. Например /\w+(?=\t)/ соответствует слову, за которым идет табуляция, но символ '\t' не включается в результат.
Пример:



$s = "1+2-3*4"; if ($s =~ /(\d)(?=-)/) # Найти цифру за которой стоит '-' { print "$1\n"; # Результат '2' } else { print "ошибка поиска\n";}

(?!шаблон) - "заглядывание" вперед по отрицанию.

Пример:



$s = "1+2-3*4"; if ($s =~ /(\d)(?!\+)/) # Найти цифру за которой не стоит '+' { print "$1\n"; # Результат '2' } else { print "ошибка поиска\n";}

(?ismx)- "внутренние" модификаторы. Удобно применять в шаблонах, где например нужно внутри шаблона указать модификатор.

Правила регулярного выражения. (regex)

Любой символ обозначает себя самого, если это не метасимвол. Если вам нужно отменить действие метасимвола, то поставьте перед ним '\'.

Строка символов обозначает строку этих символов.

Множество возможных символов (класс) заключается в квадратные скобки '[]', это значит, что в данном месте может стоять один из указанных в скобках символов. Если первый символ в скобках это '^' - значит ни один из указанных символов не может стоять в данном месте выражения. Внутри класса можно употреблять символ '-', обозначающий диапазон символов. Например, a-z - один из малых букв латинского алфавита, 0-9 - цифра и т.д.

Все символы, включая специальные, можно обозначать с помощью '\' как в языке С.

Альтернативные последовательности разделяются символом '|' Заметьте что внутри квадратных скобок это обычный символ.

Внутри регулярного выражения можно указывать "подшаблоны" заключая их в круглые скобки и ссылаться на них как '\номер' Первая скобка обозначается как '\1'.

[Назад] [Содержание] [Вперед]


Синтаксис.


Декларации (объявления)

Простое предложение

Сложные предложения

Циклы

while

Операторы управления циклом

next

last

redo

for

foreach

Блоки и оператор switch

Оператор goto

POD операторы. Документирование программ

Perl программа (скрипт) состоит из последовательности деклараций и предложений. Единственно что должно быть обязательно декларировано, это форматы отчетов и подпрограммы (функции). Все необъявленные переменные, массивы имеют значение 0 или null.

Декларации (объявления).

Perl имеет свободный формат. Комментарии начинаются с символа '#' и продолжаются до конца строки. Декларации могут использоваться в любом месте программы так же как и предложения (statements), но действуют они только в фазе компиляции программы. Обычно их помещают или в начале или в конце программы. Декларация подпрограмм позволяет использовать имя подпрограммы как списковый оператор, начиная с момента декларирования.

Пример:

sub test; # Декларация подпрограммы test

$var1 = test $0; # Использование как оператора списка.

Декларации подпрограмм могут быть загружены из отдельного файла предложением require или загружены и импортированы в текущую область имен предложением use. Подробно см. главу Модули.

Простое предложение.

Простое предложение обязательно заканчивается символом ';' если только это не последнее предложение в блоке где ';' можно опустить. Заметьте, что существуют операторы такие как eval{} и do{}, которые выглядят как сложные предложения, но на самом деле это термы и требуют обязательного указания конца предложения.

Любое простое предложение может содержать single модификатор перед ';'. Существуют следующие single модификаторы:

if EXPR unless EXPR while EXPR until EXPR

где EXPR - выражение, возвращающее логическое значение true или false. Модификаторы while и until вычисляются в начале предложения кроме блока do, который выполняется первым.

if EXPR- Модификатор "если". Предложение выполняется, если EXPR возвращает true.

Пример:

$var = 1; $var2 = 3 if $var > 0; # Результат: $var2 = 3


while EXPR - Модификатор "пока". Предложение выполняется пока EXPR = true
Пример:
$var = 1; print $var++ while $var < 5; # Печать $var с инкрементом
Результат: 1234
until EXPR- Модификатор "до ". Предложение выполняется до тех пор пока EXPR = false
Пример:
$var = 1; print $var++ until $var > 5; # Печать $var с инкрементом
Результат: 12345
unless EXPR - Модификатор "если не" . Обратный к if. Выражение выполняется если EXPR = false.
Пример:
$var = 1; print $var++ unless $var > 5; # Печать $var с инкрементом
Результат: 1
Сложные предложения.
Последовательность простых предложений, ограниченная функциональными ограничителями, называется блоком. В Perl это может быть целый файл, последовательность предложений в операторе eval{} или чаще всего это множество простых предложений, ограниченных круглыми скобками '{}'.
Существуют следующие виды сложных предложений:
if (EXPR) BLOCK

if (EXPR) BLOCK else BLOCK

if (EXPR) BLOCK elsif (EXPR) BLOCK ... else BLOCK
LABEL while (EXPR) BLOCK

LABEL while (EXPR) BLOCK continue BLOCK

LABEL for (EXPR; EXPR; EXPR) BLOCK

LABEL foreach VAR (LIST) BLOCK

LABEL BLOCK continue BLOCK
Обратите внимание, что сложные предложения описаны в термах блоков, а не предложений, как в языках C или Pascal. Поэтому необходимо всегда использовать круглые скобки для обозначения блока.
if (EXPR) BLOCK - Вычисляется логическое выражение EXPR и если true блок выполняется.

Пример:
$var =1; if ($var == 1) { print $var,"\n"; }
Результат: 1
if (EXPR) BLOCK else BLOCK2 - Если EXPR=true выполняется BLOCK иначе BLOCK2.

Пример:
$var =2; if ($var == 1) { print "\$var = 1\n"; } else { print "\$var не равно 1\n"; }
Результат: $var не равно 1
if (EXPR1) BLOCK1 elsif (EXPR2) BLOCK2 ... else BLOCK - Если EXPR1=true выполняется BLOCK1 иначе если EXPR2=true выполняется BLOCK2 иначе ... иначе BLOCK.

Пример:
$var = 1; if ($var == 0) { print "\$var = 0\n"; } elsif ($var == 1) { print "\$var = 1\n"; } else { print "Не известное \$var\n"; }


Результат: $var = 1
Цикл While
Цикл while выполняет BLOCK до тех пор пока EXPR = true. Метка LABEL не обязательна и состоит из идентификатора, завершающегося символом ':'. Метка необходима при использовании внутри блока цикла управляющих операторов next, last и redo. Если метка все же отсутствует, то эти операторы ссылаются к началу ближайшего цикла. Блок после continue выполняется всегда перед тем как вычисляется логическое выражение EXPR. Это подобно EXPR3 в предложении for, поэтому в этом блоке удобно изменять счетчики и флаги цикла даже если применяется оператор next.
Операторы управления циклом.
next - подобен continue в С. Переходит к началу текущего цикла т.е. повторяет итерацию.
Пример:
M1: while ($i < 6) { ++$i; # Увеличиваем счетчик на 1 next M1 if $i < 3; # Переходим в начало если $i < 3 ++$i; # иначе увеличиваем счетчик еще раз на 1 } continue { print "$i "; # Печатаем $i }
Результат: 1 2 4 6
last - подобен оператору break в языке С. Немедленно прерывает цикл. Блок continue пропускается.
Пример:
M1: while ($i < 6) { ++$i; # Увеличиваем счетчик на 1 last M1 if $i > 3; # Выход из цикла если $i > 3 ++$i; # иначе увеличиваем счетчик еще раз на 1 } continue { print "$i "; # Печатаем $i }
Результат: 2 4
redo - начать новый цикл не вычисляя EXPR и не выполняя continue блок.
Пример:
M1: while ($i < 6) { ++$i; # Увеличиваем счетчик на 1 redo M1 if $i == 3; # Далее пропустить для $i = 3 ++$i; # иначе увеличиваем счетчик еще раз на 1 } continue { print "$i "; # Печатаем $i }
Результат: 2 5 7
Цикл for.
LABEL for (EXPR1; EXPR2; EXPR3) BLOCK

Оператор for полностью аналогичен оператору for в С. В перед началом цикла выполняется EXPR1, если EXPR2 = true выполняется блок, затем выполняется EXPR3.
Пример:
for ($i = 2; $i < 5; ++$i) { print $i, " "; } print "\nПосле цикла i = $i\n";
Результат:
2 3 4

После цикла i = 5
Цикл foreach.
LABEL foreach VAR (LIST) BLOCK

Переменной VAR присваивается поочередно каждый элемент списка LIST и выполняется блок. Если VAR опущено, то элементы присваиваются встроенной переменной $_. Если в теле блока изменять значение VAR то это вызовет изменение и элементов списка т.к. VAR фактически указывает на текущий элемент списка. Вместо слова foreach можно писать просто for - это слова синонимы.


Пример:
@месяц = ("январь","февраль","март"); # Создали массив foreach $i (@месяц) { print $i," "; # Печать $i }
Результат: январь февраль март
Пример:
@месяц = ("январь","февраль","март"); # Создали массив foreach $i (@месяц) { $i = uc($i); # Перевели в верхний регистр } print @месяц;
Результат: ЯНВАРЬФЕВРАЛЬМАРТ
Пример:
for $i (3,5,7) { print "$i "; }
Результат: 3 5 7
Блоки и оператор switch.
Блок не зависимо от того имеет он метку или нет семантически представляет собой цикл который выполняется один раз. Поэтому действие операторов цикла next, last, redo - аналогично описанному выше. Блоки удобны для построения switch (переключатель) структур. В Perl нет специального оператора switch подобного языку С поэтому вы сами можете создавать удобные для вас конструкции. Опыт автора показывает что для простоты написания лучше всего подходит конструкция вида if ... elsif ... else ... хотя можно сочинить и нечто подобное:
SWITCH: { if ($i ==1 ) { .....; last SWITCH; } if ($i ==2 ) { .....; last SWITCH; } if ($i ==3 ) { .....; last SWITCH; } $default = 13; }
Выбирайте сами по своему вкусу.
Оператор goto.
В Perl существует оператор goto хотя где , как и когда его применять как говорил Ходжа Насреддин "Тонкий философский вопрос". Для начинающих программистов которым от так "нужен" я бы вообще посоветовал "забыть" о его существовании. Однако при создании больших производственных задач на последнем этапе особенно при отработке "отвальных" ошибочных ситуаций конечно goto нужен.
В Perl реализовано три формы goto. goto - метка, goto - выражение и goto - подпрограмма.

goto
goto - выражение
goto подпрограмма
метка выполняет непосредственный переход на указанную метку.
Вычисляет имя метки и делает соответствующий переход. Например если мы хотим сделать переход на одну из трех меток "M1:", "M2:" или "M3:" в зависимости от значений переменной $i равной 0, 1 или 2 то это лучше сделать следующим образом:
goto ("M1", "M2", "M3")[$i];
здесь $i используется как индекс массива указанного непосредственно в выражении.
довольно редкий случай т.к. всегда проще и надежней вызвать подпрограмму "естественным" образом.

POD операторы. Документирование программ.
В Perl реализован очень удобный механизм для написания документации в момент создания программы. Для этого применяются специальные POD операторы. Если в теле программы интерпретатор встречает оператор начинающийся с символа '=' например:
= head Набор стандартных процедур
то пропускается все до слова '=cut'. Это удобно для включения длинных на несколько строк или страниц комментариев. Затем с помощью специальной программы pod можно отделить текст документации от текста программы.
[Назад] [Содержание] [Вперед]

Встроенные функции.


Встроенные функции используются как термы выражений и подразделяются на две категории: списковые операторы и унарные операторы. Это влияет на их приоритет по отношению к оператору ',' - запятая. Списковые операторы могут иметь множество (список) аргументов, а унарные только один. Таким образом, запятая завершает аргументы унарного оператора и разделяет аргументы спискового. Аргумент унарного оператора воспринимается обычно в скалярном контексте, а спискового как в скалярном, так и списковом, причем скалярные аргументы идут первыми. В дальнейшем списковые аргументы мы будем обозначать словом 'LIST', это значит, что функция имеет список аргументов, разделенных запятой. Аргументы функций можно заключать в круглые скобки и таким образом обозначать, что "это функция" и приоритет не имеет значения, иначе это списковый или унарный оператор с определенным фиксированным приоритетом. Пробел после имени функции и скобкой значения не имеет. Поэтому будьте внимательны!

Пример:

print 1 + 2 + 3; # результат 6

print(1+2)+3; # результат 3

print (1+2)+3; # опять 3

print (1+2+3); # 6

Если функция возвращает результат как в скалярном так и в списковом контексте, то код выхода по ошибке - скаляр c неопределенным значением или пустой список.

Запомните правило:

Не существует общего правила преобразования списка в скаляр!

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

Оператор '-X', abs, accept, alarm, atan2 Y, X, bind, binmode, bless, caller, chdir, chmod, chomp, chop, chown, chr, chroot, close, closedir, connect, cos, crypt, dbmclose, dbmopen, define, delete, die, do BLOCK, do подпрограмма, do выражение, dump, each, eof, eval, exec, exists, exit, exp, fcntl, fileno, flock, fock, format, formline, getc, getlogin, getpeername, getpgrp PID, getppid, getpriority, Группа системных вызовов, getsockname, getsockopt, glob, gmtime, goto, grep, hex, import, index, int, ioctl, join, keys, kill, last, lc, lcfirst, length, link, listen, local, localtime, log, lstat, m//, map, mkdir, msgctl, msgget, msgsnd, msgrcv, my, next, no Module, oct, open, opendir, ord, pack, pipe, pop, pos, print, printf, push, q/строка/, qq/строка/, qx/строка/, qw/строка/, quotemeta, rand, read, readdir, readlink, recv, redo, ref, rename, require, reset, return, reverse, rewindir, rindex, rmdir, s///, scalar, seek, seekdir, select, select RBITS, WBITS, EBITS, TIMEOUT, semctl, semget, semop, send, setpgrp, setpriority, setsockopt, shift, shmget, shmget, shmread, shutdown, sin, sleep, soket, soketpair, sort, splice, split, sprintf, sqrt, srand, stat, study, substr, symlink, syscall, sysread, system, syswrite, tell, telldir, tie, time, times, tr///, truncate, uc, ucfirst, umask, undef, unlink, unpack, untie, unshift, use, utime, values, vec, wait, waitpid, wantarray, warn, write, y///


Оператор '-X'.

-X указатель файла -X выражение -X

Проверка файла, где 'X' - одно из ниже описанных значений. Это унарный оператор с одним аргументом - либо именем файла, либо указателем файла. Проверяет одно из условий. Если аргумент не указан, то берется значение переменной $_. Для ключа -t - STDIN. Результат 1, если true, '', если false или неопределенное значение, если файл не найден. Несмотря на странный вид это унарный оператор с соответствующим приоритетом. Аргумент можно заключать в круглые скобки. 'X' имеет следующие значения:

-r Файл разрешен на чтение эффективным uid/gid
-w на запись -//-
-x исполнение -//-
-o принадлежит эффективному uid (идентификатор пользователя)
-R Файл разрешен на чтение реальным uid/gid
-W на запись -//-
-X исполнение -//-
-O принадлежит реальному uid
-e файл существует
-z пустой
-s не пустой
-f обычный текст
-d директория
-l символическая ссылка
-p pipes (конвейер)
-S socket (гнездо)
-b специальное блочное устройство
-c -//- символьное -//-
-t указатель на уст-во tty
-u установлен бит setuid
-g -//- setgid
-k -//- sticky
-T текстовой файл
-B двоичный
-M "возраст" файла в днях на момент старта скрипта
-A дней с последнего чтения
-C дней с последней модификации inode
abs выражение

Абсолютное значение выражения

accept NEWSOCKET, GENERICSOCKET

Открыть новый сокет по внешнему запросу. Аналогично системному вызову accept(). Возвращает адрес или false в случае неудачи.

alarm секунды

Послать сигнал SIGALARM текущему процессу по истечении указанного промежутка времени. Не допустимо делать несколько вызовов одновременно в одном промежутке времени. Возвращает остаток времени предыдущего счетчика.

atan2 Y, X

Арктангенс отношения Y к X в пределах от -pi до +pi.

bind сокет, имя

Назначить сетевой адрес сокету. Подобно системному вызову bind. Возвращает true в случае успеха и false иначе. Имя - пакетный адрес сокета.



binmode файл

Открыть файл для двоичного (binary) режима доступа. В обычном режиме при вводе символы CR LF транслируются в LF, а при выводе LF транслируется в CR LF.

bless ссылка, класс

bless ссылка

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

caller выражение

caller

Возвращает контекст вызова текущей подпрограммы. В скалярном контексте true если это подпрограмма или процедура вызванная операторами eval() или require() и false - иначе. В списковом это список ($package, $filename, $line), где

$package - имя пакета

$filename - имя файла пакета

$line - номер строки откуда был сделан вызов.

Если указано выражение то возвращается список:

($package, $filename, $line, $subroutine, $hasargs, $wantargs)

Выражение определяет "глубину" вложенности просмотра стека вызовов.

$subroutine - имя подпрограммы

$hasargs - имеющиеся аргументы

$wantargs - необходимые аргументы

Применение данной функции в DB пакете возвращает более детальную информацию. К списку аргументов добавляется список @DB::args.

chdir выражение

Перейти в директорию указанную выражением. Если выражение отсутствует то перейти в "домашнюю" директорию. Возвращает true в случае успеха и false - неудачи.

chmod список

Изменить права доступа к файлам указанным в списке. Первый элемент в списке - числовое ,обычно восьмеричное значение прав. Возвращает количество файлов которым были изменены права.

Пример:

chmod 0666 'f1', 'f2', 'f3';

chomp переменная

chomp список

chomp

Удаляет в конце строки символ указанный переменной $/. Обычно это 'LF'. Возвращает количество удаленных символов. Если переменная не указана то используется переменная $_. Если указан список то обрабатывается каждая строка списка и возвращается общее количество удаленных символов.



chop переменная

chop список

chop

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

chown список

Изменить "владельца" и "группу" файлов списка. Первый элемент - номер нового владельца, второй номер новой группы а далее список файлов. В большинстве Unix-систем вы не сможете сменить владельца если вы не суперпользователь, но можете изменить группу если это одна из ваших "вторичных" групп.

chr число

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

chroot директория

Сделать "корневой" указанную директорию. "Корневая" - значит внутри программы на нее можно ссылаться как '/'.

close файл

Закрыть открытый файл или поток. Можно не использовать, если один и тот же файл открывается повторно, т.к. он будет автоматически закрываться новым вызовом open().

closedir директория

Закрыть директорию, открытую функцией opendir().

connect сокет, имя

Связаться с удаленным сокетом. Данная функция подобна системному вызову connect(). Возвращает true в случае успеха и false при ошибке.

cos выражение

Косинус выражения в радианах.

crypt текст, salt

Шифрация текста. Аналогично системному crypt().

dbmclose хеш

Закрывает связь между хеш и базой данных.

dbmopen хеш, база, режим

Ассоциировать указанный хеш и базу в определенном режиме. Дело в том, что в Perl реализован очень удобный механизм работы с базами данных типа dbm, ndbm, sbdm, gdbm и Berkeley DB. Для этого нужно связать (открыть) базу под именем хеша. Вся работа с записями базы выполняется так, будто это обычный хеш (ассоциативный массив). Более подробно смотрите описание функции AnyDBM().

define выражение

Возвращает true, если значение определено (существует) и false, если нет. Многие операции завершаются неопределенным значением, например чтение после конца файла, использование неопределенных переменных, системные ошибки и т.д. Данная функция позволяет различать нулевое и неопределенные значения, определенность или неопределенность функций или ссылок. При использовании определенности ключа в хеше она возвращает определен данный ключ или нет, но не существует он или нет.



delete выражение

Удалить значение из хеша. Возвращает удаляемое значение или неопределенность, если ничего не удаляется. Удаление из массива окружения $ENV{} - изменяет окружение. Удаление из хеша связанного с базой данных - удаляет запись в базе данных.

die список

Если программа не была запущена из eval(), данная функция выводит список в поток STDERR и завершает работу программы с кодом из переменной $!. Если $! содержит 0, то с кодом ($? >> 8). Если и это 0, то с кодом 255. При вызове из eval()

сообщение об ошибке заносится в переменную $@, и eval()

завершается с неопределенным значением. Это позволяет отрабатывать ошибочные ситуации, не завершая головной модуль. Если строка из списка не завершается символом '\n', то дополнительно печатается номер строки скрипта, откуда вызвана функция и номер входной строки, если таковой имеется.

do BLOCK

Это не совсем функция. Здесь возвращается значение последнего оператора блока. Когда используется циклический модификатор BLOCK исполняется перед проверкой условия цикла в отличии от обычных циклов.

do подпрограмма

Устаревший метод вызова подпрограмм.

do выражение

Значение выражения воспринимается как имя файла Perl скрипта. Изначально это применялось для включения подпрограмм библиотеки. Сейчас правильней использовать вызовы use() и require(), которые обеспечивают контроль ошибок и завершения.

dump метка

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

Внимание! Файлы, открытые до момента дампа, не будут открытыми в момент исполнения новой программой.

each хеш

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



eof файл

eof()

eof

Возвращает 1, если выполняется чтение после конца или чтение из не открытого файла. Аргументом должно быть выражение, возвращающее существующий указатель файла. Данную функцию нельзя использовать для чтения файлов, открытых как терминалы. Если аргумент не указан, то используется последний читаемый файл. Использование в форме eof() целесообразно применять в циклах while(<>) для определения конца только последнего файла из списка. Применяйте eof(ARGV) или eof для определения конца каждого файла из списка.

eval выражение

eval блок

Выражение сканируется и выполняется как обычная Perl программа. Это делается в контексте текущей программы, поэтому можно использовать уже определенные переменные и подпрограммы. Возвращается результат последнего оператора в блоке или значение оператора return. Если обнаружится синтаксическая ошибка или выполнится оператор die, то возвращается неопределенное значение, а переменная $@ содержит сообщение об ошибке. Если ошибки не было, то $@ содержит нулевую строку. При отсутствии аргумента берется значение переменной $_.

exec список

Выполняется системная команда из списка, и выполнение программы завершается. Если вам необходимо вернуться, то лучше применяйте функцию system(). Если в списке количество аргументов больше 1 или список - это массив с количеством элементов больше 1, то выполняется системный вызов execvp() с аргументами из списка. Если один скалярный аргумент, то он сканируется на обработку метасимволов, и если они присутствуют, то полученные аргументы передаются интерпретатору /bin/sh -c для дальнейшей обработки. Если метасимволов нет, то аргумент расщепляется на слова и передается системному вызову execvp(), что более эффективно.

Внимание! exec() и system(0) не сбрасывают буфер ввода/вывода, поэтому необходимо установить переменную $| для предотвращения потери выходной информации.

exists выражение

Возвращает true, если существует указанный ключ хеша, даже если не определено его значение.

exit выражение



Выполнение программы завершается с кодом выражения.

exp выражение

Возвращает e (основание натурального логарифма) в степени выражения.

fcntl файл, функция, скаляр

Выполняет системный вызов fcntl(). Для использования обязательно выполнить use Fcntl;

fileno файл

Возвращает описатель файла для данного указателя файла.

flock файл, операция

Системный вызов flock()

fock

Системный вызов fock(). Возвращает pid потомка для родителя и 0 - для потомка в случае успеха, иначе - неопределенное значение.

format

Декларативная функция Perl. Определяет формат вывода для оператора write. Подробно смотрите главу Форматы.

formline формат, список

Внутренняя функция, используемая в format. Форматирует вывод параметров из списка. Результат помещается в переменную $^A Функция write просто выводит значение этой переменной, но ее так же можно читать, а затем обнулять. Обычно format выполняет один вызов formline для одной строки формы, но formline не разделяет строки формата. Это значит что символы '~' и '~~' рассматривают весь формат как одну строку, поэтому необходимо использовать многострочные формы для описания одной записи формата.

getc файл

getc

Читает и возвращает символ из указанного файла. Если файл не указан, то читается STDIN. После конца файла возвращает пустую строку.

getlogin

Возвращает текущий login из файла /etc/utmp Не применяйте для идентификации пользователя, он не так сильно "закрыт" как getpwuid().

getpeername сокет

Возвращает упакованный адрес удаленного сокета.

getpgrp PID

Возвращает группу процесса с указанным PID. Если аргумент отсутствует, возвращает группу текущего процесса.

getppid

Возвращает PID родительского процесса.

getpriority WHICH, WHO

Возвращает текущий приоритет процесса, группы процессов или пользователя.

Группа системных вызовов:

getpwnam NAME

getgrnam NAME

gethostbyname NAME

getnamebyname NAME

getprotobyname NAME

getpwuid UID

getgrid GID

getservbyname NAME, PROTO

gethostbyaddr ADDR, ADDRTYPE

getnetbyaddr ADDR, ADDRTYPE



getprotobynumber NUMBER

getservbyport PORT, PROTO

getpwent

gethostent

getnetent

getprotoent

getservent

setpwent

setgrent

sethostent STAYOPEN

setnetent STAYOPEN

setprotoent STAYOPEN

setservent STAYOPEN

endpwent

endgrent

endhostent

endnetent

endprotoent

endservent

Все эти функции аналогичны одноименным системным вызовам. В списковом контексте возвращают следующие списки:

($name, $passwd, $uid, $gid, $quota, $comment, $gcos, $dir, $shell) = getpw*

($name, $passwd, $gid, $members) = getgr*

($name, $aliases, $addrtype, $length, @addrs) = gethost*

($name, $aliases, $addrtype, $net) = getnet*

($name, $aliases, $proto) = getproto*

($name, $aliases, $port, $proto) = getserv*

В скалярном контексте возвращается имя или что-то другое, в зависимости от типа функции. Элемент $members в вызове getgr содержит разделенные пробелом имена членов группы. @addrs содержит IP адреса компьютеров в сети Интернет в упакованном виде. Для распаковки применяйте: ($a, $b, $c, $d) = unpack('C4',$addr[0]);

getsockname сокет

Возвращает упакованный адрес сокета локальной машины.

getsockopt сокет, уровень, опция

Возвращает опцию сокета.

glob выражение

Возвращает список файлов, удовлетворяющих выражению с '*', как в команде ls.

gmtime выражение

Переводит местное время, полученное функцией time(), во время по Гринвичу. Обычно используется в виде:

($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=gmtime(time);

goto метка

goto выражение

goto &подпрограмма

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

Например:

goto ('метка1', 'метка2', 'метка3')[$i];

Здесь при $i = 0 будет переход на 'метка1', $i = 1 на 'метка2' и т.д. Третья форма (goto &подпрограмма) довольно "хитрый" метод подмены имени вызываемой подпрограммы именем текущей. Это используется в методе автозагрузки, когда нужно запустить другую процедуру, но под именем текущей, как будто та была вызвана раньше.



grep блок, список

grep выражение, список

Выполнят блок или выражение для каждого элемента списка. Переменная $_ содержит текущий элемент. Возвращает список элементов, с которыми выражение дало результат true. В скалярном контексте возвращает количество результатов true.

hex выражение

Воспринимает выражение как строку шестнадцатеричных цифр и возвращает десятичное значение.

import

В Perl нет встроенной функции import, но есть метод, с помощью которого модули могут экспортировать область имен другим модулям. Подробно смотрите функцию use().

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

index строка, подстрока

Возвращает позицию первого вхождения подстроки в строке, начиная с указанной позиции. Если позиция отсутствует, то сравнение начинается с начала строки. Отсчет позиции ведется с 0, если только не изменено значение встроенной переменной $[. Если подстрока не найдена, то результат меньше первой позиции на 1. Обычно это -1.

int выражение

Возвращает целую часть выражения.

ioctl FILEHANDLE, FUNCTION, SCALAR

Выполняет системный вызов ioctl(). В начале программы необходимо указать: require "ioctl.ph";

join выражение, список

Соединяет строки списка или массива в одну строку с кодом разделителя, равному выражению.

keys хеш

Возвращает массив всех ключей хеша. В скалярном контексте - количество ключей. Порядок следования ключей аналогичен порядку в each функции.

kill список

Послать сигнал (первый элемент) указанным в списке процессам. Возвращает количество процессов которые сигнал приняли.

last метка

last

Функция аналогичная break в С. Прерывает цикл и переходит на указанную метку. Если метки нет на ближайший внешний цикл. Блок continue не выполняется.

lc выражение

Преобразовать строку в буквы нижнего регистра.

lcfirst выражение

Заменить первую букву строки на малую.

length выражение

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

link OLDFILE, NEWFILE

Создать файл NEWFILE связанный с файлом OLDFILE.

listen SOCKET, QUEUESIZE

Выполнить системный listen().

local список



Объявляет перечисленные переменные как локальные в текущем блоке или подпрограмме. Если указано два и более имени, их необходимо заключить в круглые скобки. Предпочтительней использовать функцию my().

localtime выражение

Преобразовать 9-элементный массив, возвращаемый функцией time, относительно местного времени. Употребляется как:

($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);

log выражение

Возвращает натуральный логарифм выражения.

lstat файл

lstat выражение

То же что и системный вызов stat(), но касательно ссылки на файл, а не самого файла.

m//

Оператор совпадения. Смотри главу Операторы

map блок, список

map выражение, список

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

mkdir директория, права

Создать директорию с указанными правами доступа. Возвращает 1 при успехе, и 0 при неудаче.

msgctl ID, CMD, ARG

Системный вызов msgctl() System V

msgget KEY, FLAGS

Системный вызов msgget() System V

msgsnd ID, MSG, FLAGS

Системный вызов msgsnd() System V

msgrcv ID, VAR, SIZE, TYPE, FLAGS

Системный вызов msgrcv() System V

my список

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

next метка

next

Аналогичен continue в С. Переход к следующей итерации в цикле. Если в цикле присутствует блок continue, он так же выполняется. Если метка отсутствует - переход на ближайший внутренний цикл.

no Module список.

Исключить использование указанных модулей.

oct выражение

Возвращает десятичное число, представленное восьмеричными цифрами.

open файл, выражение

open файл

Открыть файл с указанным именем. Аргумент "файл" - это фактически указатель на блок описания файла. Если имя (выражение) файла отсутствует, то имя считается таким же как и указатель файла. Если перед именем стоит символ '<' то файл открывается только на чтение (значение по умолчанию). Если '>' - на запись. Если '>>' - на добавление записей. '+>' или '+<' - файл открыт на чтение и запись одновременно. Если имя файла начинается с символа '|', то имя считается системной командой, на вход которой выводятся данные (поток). Имя '-' - стандартный вход (STDIN), '>-' - стандартный вывод (STDOUT). Функция возвращает true при успехе и false - неудаче.



Если имя (выражение) начинается с символов ">&", то остаток имени считается именем указателя файла, который открывается повторно. Символ '&' может стоять после '<', '>>', '+>', '+>>' и '+<'. Режим повторного открытия должен соответствовать первому. Выражение вида "<&=N" где N -число, эквивалентно системному вызову fdopen(). Если имя "|-" или "-|", то происходит "расщепление" (fork) процесса на потомка и родителя. При этом возвращается номер процесса потомка (PID) внутри родительского процесса и 0 - внутри потомка. При этом запись/чтение в файл родительским процессом воспринимается как чтение/запись потомком. Для потомка это стандартный ввод/вывод. Родительский процесс ждет завершения потомка после закрытия потока и получает код завершения в переменной $?. Имя файла не должно содержать пробелов как в начале, так и в конце.

opendir указатель, выражение

Открыть директорию с именем выражения для обработки функциями readdir(), telldir(), seekdir(), rewinddir() и closedir(). Возвращает true при успехе.

ord выражение

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

pack шаблон, список

Упаковывает список в двоичную структуру по шаблону. Шаблон - это строка символов, описывающая порядок и тип упакованных значений.

A - текстовая строка, добавляется пробелами.

a - текстовая строка, добавляется 0 символом.

b - битовая строка (возрастающая нумерация бит)

B - битовая строка (убывающая нумерация бит)

h - шестнадцатеричная строка ( младший байт - первый)

H - шестнадцатеричная строка (старший байт первый)

c - символ со знаком

C - символ без знака.

s - короткое целое (один байт) со знаком.

S - короткое целое без знака.

i - целое (два байта) со знаком.

I - целое без знака.

l - длинное целое (4 байта) со знаком.

L - длинное целое без знака.

n - короткое в "сетевом" формате.

N - длинное в "сетевом" формате.

v - короткое в "VAX" формате.

V - длинное в "VAX" формате.



f - single float.

F - double float.

p - указатель на строку ограниченную 0.

P - указатель на структуру с фиксированной длиной.

u - упаковка uuencode.

x - нуль-байт

X - резервный байт.

@ - заполнить нулями позицию.

За каждой буквой может стоять число означающее количество повторов. Для всех типов за исключением 'a', 'A', 'b', 'B', 'h' и 'H', упаковывается максимально возможное количество значений из списка. Символ '*' после типа означает использовать оставшиеся параметры. Тип 'a' и 'A' использует только одно значение из списка и добавляет остаток поля либо нуль-символами, либо пробелами (при распаковке по типу 'A' пробелы и нули отбрасываются, а по 'a' - нет). Типы 'b' и 'B' упаковывают строку в указанное число бит. Так же как и 'h' и 'H' в число ниблов (байт). 'P' - упаковывает указатель на структуру с указанной длиной. Числа с плавающей запятой (floats и double) записываются в стандартном для каждой машины формате и могут быть разными для разных типов машин. Заметьте, что Perl всегда использует двойную точность (double), поэтому упаковка и распаковка по типу 'f' приведет к потере точности. Шаблоны для распаковки и упаковки совершенно одинаковы.

Примеры:

print(pack("ccc",65,66,67)); # Результат ABC

print(pack("A4A3","ab","cdefg")); # "ab cde"

print(pack("a4a3","ab","cdefg")); # "ab\0\0cde"

pipe READHANDLE, WRITEHANDLE

Аналогичен системному pipe().

pop массив

Удаляет и возвращает последний элемент массива. Длина массива уменьшается на 1. Результат не определен, если массив пустой. Если имя массива отсутствует, то извлекает из @ARGV для головной программы и @_ для подпрограммы.

pos скаляр

Возвращает смещение от последнего m//g поиска.

print файл список

print список

print

Выводит строку или список строк в файл. Возвращает true при успехе. Аргумент файл может быть скалярной переменной, содержащей имя указателя файла, если он отсутствует, то осуществляется вывод в стандартный выходной поток STDOUT (если не было вызова select()). Если список отсутствует, то выводится значение переменной $_. Для вывода по умолчанию в другой файл необходимо использовать функцию select(). Так как print работает в списковом контексте, то все элементы списка так же вычисляются в списковом контексте, т.е. функции будут возвращать списковые значения. Аргументы можно заключать в круглые скобки. Если указатель файла - элемент массива, то элемент нужно заключить в фигурные скобки для вычисления блока.



printf файл список

printf список

Аналогичен вызову "print файл sprintf(список)". Первый элемент списка должен быть форматом printf(), как и в С.

push массив, список

Добавить элементы массива значениями из списка. Длина массива увеличивается на количество элементов списка.

q/строка/

qq/строка/

qx/строка/

qw/строка/

Обычные операторы строк. Смотри главу Операторы.

quotemeta выражение

Вычисляет выражение, в котором метасимволы рассматриваются как обычные символы.

rand выражение

rand

Возвращает случайное число в диапазоне между 0 и выражением. Если выражение отсутствует - между 0 и 1. Данная псевдослучайная последовательность сбрасывается функцией srand().

read файл, скаляр, длина, смещение

read файл, скаляр, длина

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

readdir директория

Возвращает имя следующего файла в директории открытой командой opendir(). В скалярном контексте возвращает все оставшиеся имена файлов. Если файлов больше нет, то возвращает неопределенность в скалярном контексте и пустую строку в списковом.

readlink выражение

Возвращает значение символической ссылки. При ошибке возвращает неопределенное значение.

recv SOCKIT, SCALAR, LEN, FLAGS

Получить сообщение из сокета. Аналогичен системному recvfrom().

redo метка

redo

Перейти к началу блока, минуя вычисление условия и блока continue. Если метка отсутствует, то переход к ближайшему внешнему блоку.

ref выражение

Возвращает true, если выражение это ссылка, иначе - false. Возвращаемое значение зависит от типа ссылки. Существуют следующие типы ссылок:

REF, SCALAR, ARRAY, HASH, CODE, GLOB

Если аргумент - ссылка на класс, то возвращается имя класса. Функция ref() аналогична функции typeof().

rename старое_имя, новое_имя_файла

Переименовать файл. Возвращает 1 в случае успеха, иначе - 0.



105require выражение

require

Если выражение - число, требует что бы текущая версия Perl была не ниже указанной. Если строка - считывает библиотечный файл с указанным именем, если он еще не прочитан. Последний оператор библиотечного файла должен возвращать true. Обычно это строка вида 1; Если расширение имени файла отсутствует, то по умолчанию принимается ".pm" В данной функции можно указывать путь расположения файла, а если библиотека расположена в стандартной системной области Perl, то вместо require предпочтительней использовать use().

reset выражение

reset

Обычно используется в блоках continue циклов для очистки переменных и поиска для повторного применения. Выражение воспринимается как список символов. Для указания диапазона можно применять символ минус '-'. Все переменные и массивы, начинающиеся с этих символов, обнуляются. Если выражение отсутствует, то обнуляется поиск ?шаблон? для повторного поиска. Сбрасываются только переменные текущего модуля.

Пример:

reset 'a'; # очистить все переменные начинающиеся # буквой 'a' reset 'a-z' # все переменные с малых букв.

Выражение вида: 'A-Z' употреблять не рекомендуется, т.к. обнуляются важные массивы @ARGV и @ENV.

return список

Выход из подпрограммы с указанным кодом. Если данная функция отсутствует, то выход из подпрограммы осуществляется с кодом последнего выполненного оператора.

reverse список

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

rewindir директория

Устанавливает указатель файлов открытой директории в начало для последующего чтения функцией readdir().

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

rindex строка, подстрока

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

rmdir директория

Удалить указанную директорию, если в ней нет никаких файлов. Возвращает 1 при успехе и 0 - при неудаче. При этом переменная $! содержит код (errno).



s///

Оператор подстановки. Смотри главу Операторы.

scalar выражение

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

seek файл, позиция, отсчет

Установить указатель на произвольную позицию в файле. Если отсчет равен 0 - позиционировать от начала файла, если 1 - от текущего положения, 2 - от конца файла. Возвращает 1 при успехе и 0 - неудаче.

seekdir директория, позиция

Установить указатель файла в открытой директории для последующего чтения функцией readdir(). Текущая позиция может быть получена функцией telldir().

select файл

select

Возвращает текущий указатель файла- по умолчанию или делает текущим указанный. Таким образом, если в функциях print или write не указан файл вывода, то это осуществляется в файл, указанный select. Переменные, связанные с выводом, так же действуют на вывод в этот файл.

select RBITS, WBITS, EBITS, TIMEOUT

Выполняет системный select()

semctl ID, SEMNUM, CMD, ARG

Системный вызов semctl() для SYSTEM V.

semget KEY, NSEMS, FLAGS

Системный вызов semget() для SYSTEM V.

semop KEY, OPSTRING

Системный вызов semop() для SYSTEM V.

send SOCKET, MSG, FLAGS, TO

send SOCKET, MSG, FLAGS

Послать сообщение через сокет. Аналогично системному send().

setpgrp PID, PGRP

Установить номер группы PGRP процессу с номером PID, 0 - для текущего процесса.

setpriority WHICH, WHO, PRIORITY

Установить приоритет PRIORITY процессу пользователя WHO и группе WHICH.

setsockopt SOCKET, LEVEL, OPTNAME, OPTVAL

Установить параметры сокета. Возвращает неопределенность при ошибке.

shift массив

shift

Удаляет первый элемент массива и возвращает его значение. Если массив пустой, то результат - неопределенность. Если аргумент опущен - обрабатывается массив @ARGV в головной программе или @_ в подпрограмме.

shmctl ID, CMD, ARG

Системный вызов shmctl() System V

shmget KEY, SIZE, FLAGS

Системный вызов shmget() System V



shmread ID, VAR, POS, SIZE

shmread ID, STRING, POS, SIZE

Пишет или читает сегмент общедоступной памяти в System V.

shutdown SOCKET, HOW

Прекращает работу сокета методом HOW.

sin выражение

Возвращает в радианах синус выражения.

sleep выражение

sleep

Приостанавливает работу процесса на указанное число секунд или зацикливается, если аргумент отсутствует. Работа продолжается, если получен сигнал SIGALARM. Возвращает время фактической паузы.

socket SOCKET, DOMAIN, TYPE, PROTOCOL

Открывает сокет и привязывает его к указателю SOCKET.

socketpair SOCKET1, SOCKET2, DOMAIN, TYPE, PROTOCOL

Создает "безымянную" пару сокетов в указанном DOMAIN. Возвращает true при успехе и false - неудаче.

sort подпрограмма список

sort блок список

sort список

Сортирует элементы списка и возвращает полученный список. Несуществующие элементы списка отбрасываются. Если не указано имя подпрограммы или блок, то сортирует в стандартном строковом порядке. Указанная подпрограмма возвращает значения больше, меньше или равное нулю в зависимости от двух соседних элементов списка. Имя подпрограммы может быть указано переменной. Она не должна быть рекурсивной, и два сравниваемых элемента списка передаются как глобальные переменные $main::a и $main::b. Это ссылки, поэтому их изменение приводит к изменению самих элементов списка.

splice массив, смещение, длина, список

splice массив, смещение, длина

splice массив, смещение

Удаляет элементы массива, начиная со смещения и указанной длины. Заменяет их указанным списком. Возвращает удаленный список. Если длина не указана, удаляет все элементы списка, начиная со смещения.

split /шаблон/, выражение, предел

split /шаблон/, выражение

split /шаблон/

split

Разделяет строку, указанную выражением, на массив элементов и возвращает его. В скалярном контексте возвращает количество полученных элементов массива, а сам массив помещает в @_ (в списковом контексте поместить результат в @_ можно если применить ?шаблон?) Если выражение отсутствует, то обрабатывается содержимое переменной $_. Если шаблон отсутствует, то разделителем является пробел. Все, что подходит по шаблону, считается разделителем. Если указан предел, то это максимальное число разделений. Отрицательное значение предела воспринимается как неограниченно большой предел. Если пустая строка походит под шаблон разделителя, то исходное значение разделяется посимвольно. Предел удобно использовать для частичного разделения строки.



Пример:

($a, $b, $остаток) = split(/ /, "Один Два Три Четыре",3);

здесь $a = 'Один', $b = 'Два' и $остаток = 'Три Четыре'

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

Пример:

@a = split(/([,.])/, "Один,Два.Три");

здесь @a = ("Один", "," ,"Два", ".", "Три")

sprintf формат, список

Форматирует список по указанному формату аналогично функции sprintf() языка С.

sqrt выражение

Возвращает корень квадратный выражения.

srand выражение

Задает начальное значение для генератора случайных чисел - оператора rand. Если аргумент отсутствует, то используется текущее машинное время.

stat файл

stat выражение

Возвращает 13 элементный массив параметров указанного файла или пустой список при ошибке. Применяется обычно следующим образом:

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

где

$dev - имя устройства

$ino - номер i-узла

$mode - права доступа

$nlink - количество связей

$uid - идентификатор владельца

$gid - идентификатор группы

$rdev - тип устройства

$size - размер файла в байтах

$atime - дата последнего обращения

$mtime - дата последней модификации

$ctime - дата последнего изменения статуса

$blksize - размер блока на диске

$blocks - количество блоков в файле.

Если указан аргумент '_', то возвращается результат предыдущего вызова stat().

study скаляр

study

Включение метода частотного сравнения. Целесообразность применения зависит от количества поисков и количества констант в строке в которой ведется поиск. Функция работает следующим образом: Для указанного скаляра (если аргумент отсутствует берется значение переменной $_) строится список указателей на каждый символ строки. Затем, когда начинается поиск, первыми просматриваются символы, которые наиболее редко встречаются в английском языке. Выигрыш по времени очевиден, когда выполняется многократный поиск в одной и той же строке, и время затраченное на индексацию окупается.



substr выражение, смещение, длина

substr выражение, смещение

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

symlink старый_файл, новый_файл

Создает новый файл, символически связанный со старым, т.е. создает ссылку на файл. Возвращает 1 при успехе и 0 - неудаче.

syscall список

Выполняет системную функцию. Первый элемент списка - это имя функции, а остальные элементы - ее аргументы. Если функция не выполнима, то возвращается фатальная ошибка. Аргументы интерпретируются следующим образом. Если аргумент число, то оно считается целым. Если не число, то аргумент считается указателем на строку. Вам необходимо обеспечить достаточную длину аргумента для подстановки значения указателя. В Perl передается максимум 14 параметров. Обычно этого достаточно.

sysread файл, скаляр, длина, смещение

sysread файл, скаляр, длина

Прочитать из файла указанное число байт в скаляр с помощью системного вызова read(). Смещение обозначает позицию в скаляре, после которой будут вставлены прочитанные байты.

system список

Делает то же самое, что и "exec список" с той лишь разницей, что вызов fork() делается первым, и родительский процесс ждет завершения потомка. Возвращает значение аналогичное функции wait(). Для получения действительного кода завершения необходимо разделить на 256.

syswrite файл, скаляр, длина, смещение

syswrite файл, скаляр, длина

Записать в файл указанное число байт скаляра с помощью системного вызова write(). Смещение указывает позицию в скаляре, откуда начинается запись.

tell файл

tell

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

telldir директория

Возвращает текущую позицию указателя в открытой директории. Обычно это параметр для позиционирования указателя директории функцией seekdir().

tie переменная, класс, список

Присваивает переменную классу. Список - это аргументы new метода класса (TIESCALAR, TIEARRAY или TIEHASH). Возвращает указатель на созданный новый объект класса, который удобен для вызова других методов класса.



Внимание! Такие функции как keys() и values() могут вернуть в качестве значения огромное количество данных.

Для создания объекта ассоциативного типа необходимо определение следующих методов:

TIEHASH classname, LIST

DESTROY this

FETCH this, key

STORE this, key, value

DELETE this, key

EXISTS this, key

FIRSTKEY this

NEXTKEY this, lastkey

Обычного массива:

TIEHASH classname, LIST

DESTROY this

FETCH this, key

STORE this, key, value

[others TBD]

Скалярного типа:

TIEHASH classname, LIST

DESTROY this

FETCH this, key

STORE this, key, value

time

Возвращает количество секунд, начиная с 1 января 1970 г 00:00:00 UTC. Годы не разделяются на високосные.

times

Возвращает 4-х элементный массив значений:

($user, $system, $cuser, $csystem) = times;

где:

$user - пользовательское время процесса в секундах.

$system - системное время текущего процесса.

$cuser - время процесса-потомка текущего процесса.

$csystem - его системное время.

tr///

Оператор транслятор. Подробно смотри главу "Операторы".

truncate файл, длина

truncate выражение, длина

Усекает длину указанного файла.

uc выражение

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

ucfirst выражение

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

umask выражение

umask

Устанавливает маску umask и возвращает старое значение. Без аргумента возвращает текущее значение.

undef выражение undef

Делает неопределенным значение выражения. Применяется только для скалярных переменных, целых массивов или подпрограмм. Всегда возвращает неопределенное значение.

unlink список

Удаляет файлы, указанные в списке. Возвращает количество удаленных файлов. Только супервизор может удалять директории с файлами, если Perl запущен с ключом -U.

unpack шаблон, выражение

Функция, обратная pack(). Распаковывает строку выражения по указанному шаблону в массив значений. В скалярном контексте возвращает значение только первого элемента. Шаблоны такие же как и в pack().



Символ '%' в шаблоне означает, что вы хотите получить вместо значения его контрольную сумму. По умолчанию - 16-битную.

untie переменная

Исключает переменную из класса указанного tie().

unshift массив, список

Противоположное shift. Помещает элементы списка в начало массива.

use модуль список

use модуль

Указывает библиотечный модуль, из которого можно вызывать подпрограммы. Список перечисляет имена подпрограмм, которые добавляются к текущей области имен. Если не указан, то все имена. Действие аналогично блоку:

BEGIN { require модуль; import модуль список; }

Сам модуль должен располагаться в системной области Perl файлов.

utime список

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

values хеш

Возвращает обычный массив со всеми значениями хеша. В скалярном контексте возвращает количество значений хеша.

vec выражение, смещение, бит

Возвращает значение строки как вектор беззнаковых целых.

wait

Ожидать окончание порожденного процесса. Возвращает PID для родительского процесса или -1, если нет - процесса потомка. Код завершения записывается в переменную $?.

waitpid PID, FLAGS

Ожидать окончания процесса потомка с указанным PID. Возвращает либо PID этого процесса либо -1 если нет такого процесса. Код завершения записывается в переменную $?.

wantarray

Возвращает true, если подпрограмма вызывается в списковом контексте и false - в скалярном.

warn список

Выводит в стандартный поток ошибок STDERR сообщение аналогично die(), но не прекращает работу программы.

write файл

write выражение

write

Выводит в файл форматированные данные по оператору format. По умолчанию имя формата совпадает с именем указателя файла. Имя файла по умолчанию можно изменить функцией select(), а имя формата при этом надо присвоить переменной $~. Заголовок листа пишется автоматически. Если на листе не хватает места для вывода, то выводится "перевод формата" и специальная форма заголовка листа, затем сами записи. По умолчанию имя формата заголовка листа состоит из имени указателя файла и добавленной строки "_TOP". Динамически это можно делать, присваивая формат переменной $^. Количество оставшихся строк листа содержится в переменной $- и если присвоить ей 0, то произойдет смена листа. Подробно описание форматов смотри в главе Форматы.

y///

Оператор транслятор. Смотри главу Операторы.

[Назад] [Содержание] [Вперед]


Встроенные переменные Perl.


Описанные в данной главе переменные имеют в Perl специальные значения. Они обозначаются несколько непривычно для "глаза" программистов, т.к. состоят обычно только из двух символов, причем первый это '$' символ, с которого начинаются имена всех переменных, и произвольный часто не буквенно-цифровой символ. Если вы хотите пользоваться их "нормальными" буквенными синонимами, то вам нужно указать в начале программы:

use English;

Точно так же если вы захотите пользоваться переменными и методами текущего указателя файлов вы можете написать:

use FileHandle;

после этого можно просто писать:

метод указатель выражение

или

указатель -> метод(выражение)

Ниже приводятся имена как в короткой, так и в длинной (словесной) форме. Некоторые из встроенных переменных имеют доступ только на чтение, поэтому изменить их значение просто невозможно.

$_

$ARG

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

$цифра

Содержит найденную подстроку в последнем поиске, когда шаблон содержит метасимволы в круглых скобках. Цифра в данном случае, это номер скобок. Первая подстрока имеет номер 1.

$&

$MATCH

Найденная подстрока в последнем поиске по шаблону.

$`

Подстрока, предшествующая найденной подстроке.

$'

$POSTMATCH

Подстрока, последующая за найденной подстрокой.

$+

$LAST_PAREN_MATCH

Подстрока, найденная в поиске с выбором по "или".

$*

$MULTILINE_MATCHING

Если значение этой переменной установить равным 1, то переменная, в которой осуществляется поиск, будет считаться многострочной, т.е. содержащей символы '\n' - перевод строки. Если значение равно 0, то переменная считается однострочной. В Perl версии 5 и выше не рекомендуется использовать эту переменную.

$.

$INPUT_LINE_NUMBER

$NR

Номер прочитанной строки последнего оператора ввода. Закрытие файла вызывает очистку значения этой переменной.

$/

$RS

$INPUT_RECORD_SEPARATOR

Символ - признак конца входной строки. По умолчанию это '\n'


$|

$OUTPUT_AUTOFLUSH

Если присвоить этой переменной ненулевое значение, то будет сброс буфера вывода после каждой операции вывода. Значение по умолчанию - 0

$,

$OFS

$OUTPUT_FIELD_SEPARATOR

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

$\

$ORS

$OUTPUT_RECORD_SEPARATOR

Символ, добавляемый print после вывода всех параметров.

$"

$LIST_SEPARATOR

Аналогичен "$,", но добавляется после каждого элемента массива, указанного в "....".

$;

$SUBSEP

$SUBSCRIPT_SEPARATOR

Символ - разделитель для эмуляции многомерных массивов в хеш массивах. По умолчанию '\034'.

$#

$OFMT

Формат по умолчанию для вывода чисел.

$%

$FORMAT_PAGE_NUMBER

Формат по умолчанию для вывода номеров страниц.

$=

$FORMAT_LINES_PER_PAGE

Длина одной страницы. По умолчанию 60 строк.

$-

$FORMAT_LINES_LEFT

Количество оставшихся строк на странице.

$~

$FORMAT_NAME

Имя формата текущего вывода. По умолчанию имя указателя.

$^

$FORMAT_TOP_NAME

Имя текущего формата для заголовка страницы.

$:

$FORMAT_LINE_BREAK_CHARACTERS

Символы переноса строки для многострочных полей. В строке формата такие поля начинаются символом '^'. По умолчанию '\n-'.

$^L

$FORMAT_FORMFEED

Символ перевода формата ( смены листа). По умолчанию '\f'.

$^A

$ACCUMULATOR

Текущее значение аккумулятора функции write() для format(). Значение этой переменной можно увидеть только при использовании функции formline(), т.к. write() очищает ее после каждого вывода.

$?

$CHILD_ERROR

Данная переменная содержит статус завершения таких процессов как: закрытие pipe, завершение функций system(), wait() и `...`.

$!

$ERRNO $OS_ERROR

В числовом контексте возвращает код ошибки errno. В строковом - строку сообщения об ошибке. Можно принудительно присвоить этой переменной код ошибки, что бы получить системное сообщение для данного кода или установить код завершения для функции die().

$@

$EVAL_ERROR

Сообщение об ошибке последней команды eval().

$$

$PID

$PROCESS_ID

Номер текущего процесса.



$<

$UID

$REAL_USER_ID

Реальный UID текущего процесса.

$>

$EUID

$EFFECTIVE_USER_ID

Эффективный UID текущего процесса.

$( $GID

$REAL_GROUP_ID

Реальный GID текущего процесса.

$)

$EGID

$EFFECTIVE_GROUP_ID

Эффективный GID текущего процесса.

$O

$PROGRAM_NAME

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

$[

Номер первого элемента массива или символа строки. Значение по умолчанию - 0.

$]

$PERL_VERSION

Строка - сообщение версии Perl. Печатается по команде perl -v Применяется в программе для определения рабочей версии Perl. В числовом контексте это номер версии плюс номер модификации / 1000.

$^D

$DEBUGGING

Текущее значение ключа отладки '-D'.

$^F

$SYSTEM_FD_MAX

Номер максимального системного описателя файлов (system file descriptor). Обычно это 2.

$^I

$INPLACE_EDIT

Текущее значение inplace-edit возможности. Для отключения используйте undef.

$^P

$PERLDB

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

$^T

$BASETIME

Время в секундах с начала 1970 года старта текущей программы.

$^W

$WARNING

Значение флага '-w'. true -если включено и false - выключено.

$^X

$EXECUTABLE_NAME

Команда запуска Perl. Аналогично argv[0] в С.

$ARGV

Имя текущего файла, читаемого оператором '<>'.

@ARGV

Массив параметров строки запуска программы. Внимание! @#ARGV - меньше количества параметров на 1, т.к. $ARGV[0] это первый параметр (не имя программы).

@INC

Список директорий диска, которые просматривает Perl для выполнения команд do, require или use.

%INC

Этот хеш содержит имена директорий для имен использованных файлов командами do или require. Ключ - имя файла, а значение - директория.

$ENV{выражение}

Хеш %ENV содержит значения переменных окружения. Изменение этих значений вызывает изменение окружения для процессов потомков.

$SIG{выражение}

Хеш %SIG содержит имена подпрограмм для таких системных сигналов как INT, QUIT, PIPE, ... Значение 'DEFAULT' - для системной обработки. 'IGNORE' - игнорировать данный сигнал.

[Назад] [Содержание] [Вперед]


Введение в Perl


В книге приводятся начальные сведения по новому языку программирования Perl. Данный язык получил широкое распространение в связи с развитием компьютерной сети Интернет. Все примеры в книге проверены для Perl версии 5.003 операционной системы Unix FreeBSD 2.1.0.

Для программистов, системных администраторов и пользователей компьютеров.

© Маслов Владимир Викторович.

Содержание

От простого к сложному

Запуск Perl - программы

Синтаксис

Декларации (объявления)

Простое предложение

Сложные предложения

Циклы

while

Операторы управления циклом

next

last

redo

for

foreach

Блоки и оператор switch

Оператор goto

POD операторы. Документирование программ

Переменные

Контекст

Скалярные значения

Конструкторы скаляров

Конструкторы списков

Тип typeglobs

Встроенные переменные

Регулярные выражения (шаблоны)

Операторы и приоритеты

Термы и левосторонние списковые операторы

Унарные операторы

Операторы "привязки" =~ и !=

Мультипликативные операторы

Аддитивные операторы

Операторы сдвига

Именованные унарные операторы

Операторы отношений

Операторы равенства

Операторы работы с битами

Логические операторы && (AND) и || (OR)

Оператор диапазона '..'

Условный оператор '?:'

Операторы присваивания

Оператор ',' (запятая)

Логические not, and, or, xor

Операторы ограничители строк

Операторы ввода-вывода

Слияние констант

Целочисленная арифметика

Встроенные функции

Подпрограммы

Private переменные

Переменные типа local

Прототипы (prototypes)

Ссылка как параметр

Переопределение встроенных функций

Автозагрузка

Модули

Таблицы имен

Конструкторы и деструкторы

Классы

Создание библиотеки

Pragma библиотеки

Стандартные библиотеки

CPAN

Форматы отчетов

Отладка

Интернет - ссылки и литература

Все замечания и предложения направляйте по адресу:

maslov@klgtts.kaluga.su

maslov@news.kaluga.rosmail.com



Запуск интерпретатора Perl


Синтаксис:

perl [ключи] файл аргументы

Перед стартом Perl ищет скрипт (программу) в следующем порядке:

В командной строке если указан ключ '-e'

Содержимое файла указанного в командной строке. В первой строке можно указывать #!/usr/bin/perl для "автоматического" запуска скрипта.

Стандартный ввод/вывод, если не указан файл или аргументы, содержащие имя файла. Для передачи аргументов скрипту из стандартного потока, имя файла в командной строке обозначается символом '-'.

В методах 1 и 2 Perl сканирует строки, начиная с первой, если не указан ключ '-x', в противном случае началом программы считается строка с символами '#!' в начале и содержащая слово 'perl'. Концом программы считается строка '__END__'. В строке с '#!' можно указывать и ключи. Например '#!/bin/perl -d' для отладки программ.

После "обнаружения" скрипта Perl компилирует его целиком во внутреннее представление. Если обнаруживаются ошибки, то выполнение прекращается. Если ошибок нет, он выполняется. Если скрипт заканчивается без команд exit() или die(), то по умолчанию выполняется команда exit(0), обозначающая нормальное завершение программы.

Ключи:

-O цифры

Код символа-разделителя записей. По умолчанию \0.

-a

Включает режим автоматического разделения (split) переменной $_ в массив $F. Применяется с ключами -n и -p.

-c

Выполняется синтаксическая проверка скрипта и выход без запуска.

-d

Запуск в режиме интерактивной отладки.

-D число или D список

Установить флаги отладки Perl. Например -d14 проследить как Perl исполняет вашу программу.

1 p Синтаксический разбор
2 s Состояние стека
4 l Состояние стека имен
8 t Трассировка исполнения
16 o Создание оператора узла
32 c Строковое/числовое преобразование
64 p Вывод команды препроцессора для -P
128 m Распределение памяти
256 f Обработка формата
512 r Синтаксический разбор регулярных выражений
1024 x Дамп синтаксического дерева
2048 u Проверка защиты
4096 L "Утечка" памяти
8192 H Дамп хеша
16384 X Распределение scratchpad
32768 D Очистка
<
-e команда

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

-F шаблон

Указывает шаблон разделения в режиме работы с ключом -a

-i расширение

Применяется для резервной копии файла обрабатываемого оператором '<>'. Оригинал хранится в файле с тем же именем, что и исходный, но с указанным расширением.

Пример:

perl -p -i.old -e "s/рядовой/ефрейтор/" file

Поменять все слова "рядовой" на "ефрейтор" в файле file, а оригинал записать в файле file.old

-I директория

Директория includ- файлов для С препроцессора. Применяется с ключом -P по умолчанию это /usr/include и /usr/lib/perl.

-l число

Автоматическая обработка символа конца строки. Работает в двух случаях.

Отбрасывает последний символ читаемых строк для режимов -n и -p

Присваивает указанное значение переменной $\. Таким образом к концу каждой строки выводимой оператором print добавляется этот символ.

-n

Зацикливает скрипт и последовательно обрабатывает файлы указанные в командной строке. Позволяет создавать команды подобные sed или awk. Операторы BEGIN и END дают возможность делать начальные и конечные установки. Содержимое файлов не выводится.

-p

То же что и -n, но печатает обрабатываемые строки файлов.

-P

Предварительная обработка препроцессором языка С. Будьте внимательны и не применяйте в комментариях слова 'if', 'else' или 'define', т.к. это команды С - препроцессора.

-s

Включение режима обработки ключей командной строки запуска скрипта. Все аргументы с символом '-' в начале, считаются ключом, и переменным с таким же именем присваивается значение true.

-S

Использование системной переменной PATH для поиска скрипта. Данный ключ применяется в системах, невоспринимающих последовательность "#!" в начале скрипта для указания интерпретатора.

-T

Режим проверки "дыр" в защите. Обычно это нужно для программ, работающих в режиме повышенной привилегии (setuid, setguid). Желательно для CGI скриптов.

-u

Принудительный дамп памяти после компиляции скрипта. Этот дамп можно потом использовать для создания исполняемого файла с помощью программы undump.



-U

Разрешение выполнять опасные операции. Например, стереть директорию или выполнять явно не закрытую программу.

-v

Вывод номера версии Perl.

-w

Вывод имен переменных, используемых только один раз, имен скаляров, используемых до их определения, имен переопределяемых подпрограмм, ссылок на неопределенные указатели файлов, попыток записи в файлы, открытых только на "чтение", употребление некорректных записей чисел, использование массивов как скаляров, рекурсия более 100 уровней.

-x директория

Режим запуска скрипта, вставленного в файл, содержащий обычный текст. Началом скрипта считается строка с символами '#!' в начале и содержащая слово perl. Концом - строка с '__END__' Указанная директория становится текущей в момент исполнения. Если необходимо читать последующие строки, то это лучше делать через указатель файла DATA.

[Назад] [Содержание] [Вперед]


Аргументы.


Аргументы вызова функции передаются через пременную @_

sub say_hello_to { print "Hello, $_[0]!\n"; } say_hello_to("world"); sub say { print "$_[0], $_[1]!\n"; } say_hello_to("hello", "world");

Пременная @_ является локальной для подпрограммы. Если для @_

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

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

return $sum; } $a = add(4, 5, 6); print add(1..5);



Блоки операторов.


{ 1_operator; 2_operator; 3_operator; ... last_operator; # with or witout ";" }



Целочисленные литералы.


Пример:

12 15 -2004 3485

Восьмиричные числа начинаются с нуля, а шестнадцатиричные - с 0x или 0X. Пример:

0377 -0xff



CGI-программа гостевой книги.


Создание файла:

touch /usr/tmp/chatfile chmod 0666 /usr/tmp/chatfile

Блокирование доступа:

use Fcntl qw(:flock); # импортирует LOCK_EX, ... ... flock(CHANDLE, LOCK_EX) || bail("Cannot flock $CHATNAME: !$");



CGI-программирование.


Простейшая CGI-программа.

Передача параметров через CGI.

Сокращение обьема вводимого текста.

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

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

Ссылки.

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

CGI-программа гостевой книги.

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

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



Числа.


В Perl для всех чисел используется один и тот же внутренний формат - значения с плавающей запятой двойной точности.



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


Используется вызов readdir, который возвращает следующее имя файла или undef

opendir(ETC, "/etc") || die "cannot opendir /etc:$!"; while(defined($name = readdir(ETC))) { print "$name\n"; } closedir(ETC);

Или в отсортированном порядке

opendir(ETC, "/etc") || die "cannot opendir /etc:$!"; foreach $name (sort readdir(ETC)) { print "$name\n"; } closedir(ETC);



Что такое хеш.


Хеш представляет собой набор скалярных данных, отдельные элементы которого выбираются по индексному значению. Индексные значения хеша - произвольные скаляры (ключи).

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