Главная
 Сайт Андрея Зайчикова
Пятница, 10 Августа 2007г. 
Карта сайта Поиск по сайту Написать письмо  
 .:Навигатор 
Новости
Библиотека
Статьи
Олимпиады
FAQ (ЧаВо)
Гостевая книга 
Ссылки
 .:Информация 


FAQ(ЧаВо) по Perl

Общие вопросы

Что такое Perl?
Practical Extraction and Report Language. Язык программирования, который задумывался, как удобный язык для работы со строками, и не стесненный, к тому же, ограничениями, свойственными другим языкам. Фактически, получился удобный язык, на котором программы быстро пишутся (в общем случае это не значит, что они работают быстрее, например, программ С++ - но написать код можно точно быстрее)

Кто его придумал?
Larry Wall. А развивается он при помощи тысяч энтузиастов по всему миру.

Для чего его используют?
Самое распространенное использование - в качестве CGI-программ, выполняемых на интернет-сайтах.

Сколько стоит его коммерческая версия?
Мечта тех, кто разрабатывает Perl - сделать некоммерческий продукт, который будет лучше коммерческих. Это им удается, ИМХО. Perl распространяется свободно, поддержка пользователей осуществляется через ньюс-конференции и рассылки. Тем не менее, если есть желание, можно заключить контракт на поддержку за деньги.

Под какие платформы он существует?
perl 5 - под практически все виды UNIX-систем (Linux, FreeBSD, SunOS,..), DOS (защищенный режим, i386 и выше), Windows 9x/NT, OS/2, VAX VMS, Novell Netware. Amiga..

А компилятор где взять?
Пока полноценных компиляторов не существует - скрипты выполняются и распространяются в виде исходников. Hечто, заявленное, как компилятор, и подходящее только к Activestate-перлу для w32, лежит на www.activestate.com

Сайт перла какой? Где взять последнюю версию?
www.perl.com, для windows - www.activestate.com

Как сделать то-то? Может, уже есть готовая библиотека?
www.perl.com/CPAN/, search.cpan.org
CPAN - огромное, отсортированное собрание всех дополнительных модулей к perl, не включенных в поставку. Собраны все версии модулей. Рядом с ними лежат readme. Скачиваете, и устанавливаете. В 90% случаев то, что вы пытаетесь сделать, уже кто-то сделал и выложил на CPAN. Как устанавливать модули для perl w32 - см. ниже, в разделе perl+Windows

Где взять скриптов готовых, побольше?
www.cgi-resources.com, www.cgiresources.com, www.script.ru, www.codemanual.com
Только не используйте и не разбирайте скрипты из Matt's scripts archive. Он не умеет правильно их писать, лучше не учиться плохому.

А вот у меня вопрос...
Во-первых, вместе с perl поставляется уйма документации. Hачиная с perlfaq, который HЕОБХОДИМО прочесть (хотя бы просмотреть заголовки). Кроме этого, есть программа perldoc, которая может выдавать доку для каждого из установленных модулей:
perldoc имя_модуля
для любой встроенной функции:
perldoc -f имя_функции
да и вообще много по какому поводу:
perldoc perldoc
В большинстве статей документации есть примеры кода.

Какие существуют редакторы для написания программ, с подсветкой?
Мультиплатформенный - vim. Под win32 - FAR с плагином Colorer, perl scripting tool

perl+Windows

У меня перл от Activestate, как мне поставить такой-то модуль?
www.activestate.com/packages/zips/ Hаходите нужный архив, скачиваете, читаете readme. Если нужного модуля нет - идёте на CPAN, ищете его там, пытаетесь понять, как его прикрутить. С некоторой вероятностью он чисто перловый, и тогда есть шанс, что просто положив его в директорию с модулями, вы получите работающий модуль. Если же у него есть С-часть, ставите MS Visual C, и мучаетесь, мучаетесь...

А из браузера как смотреть на вывод скрипта? Почему-то показывается исходник.
Потому что между браузером и perl должен стоять сервер, который и запускает скрипт на выполнение, отдавая результат браузеру. Сервер не обязательно подразумевает под собой отдельный компьютер - вы можете поставить себе программу, и обращаться к ней через браузер, наблюдая за работой скриптов. Вариантов масса: Personal Web Server из поставки Win9x, Sambar, Apache. Устанавливаете сервер, и либо указываете в настройках сервера ассоциацию на файлы cgi и pl - запуск perl.exe, либо устанавливаете такую ассоциацию на эти файлы в windows (dbl click в windows explorer AKA проводник).

Как заставить работать связку perl + MySQL под виндой?
Скачать дистрибутив MySQL с сайта (www.mysql.com), и дистрибутив perl с этого же сайта, собранный с необходимыми модулями - DBI и DBD:MySQL.

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

А что это за закорючки такие в скрипте - s/^[^\w]{1,3}(\d+)/$1/
Это регулярные выражения, одна из мощнейших возможностей perl. Средства поиска и замены подстрок в строках

Как ими пользоваться?
Этому учатся всю жизнь. Даже целая книга есть - "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/\s1\s/g; означает "заменить все числа в строке $str, отделенные пробелами с двух сторон, на цифру 1, отделенную пробелами". Более подробное описание регулярных выражений, список управляющих символов и других возможностей смотрите в документации.

Кто-нибудь может мне по-русски рассказать о операорах: ?:, ?!, ?= и т.д. и когда они используются?
(?:pattern) - это почти (pattern). В норме круглые скобки выполняют одновременно две функции - группируют то, что у них внутри, чтобы можно было использовать повторители (*, ?, +), и сохраняют то, что там получилось, в переменных $1, $2,.. (?:pattern) выполняет только первую функцию, не трогая, таким образом, значения переменных $1, $2,... Что несколько ускоряет работу (пропорционально количеству откатов, проходящих через границу выбранной группы) и уменьшает количество переменных.
(?=pattern) - загляд вперед. Отличается от просто pattern тем, что после успешного нахождения соответствия позиция в строке будет не после соответствующего куска, а перед ним.
(?!pattern) - отрицательный загляд вперед. Отличается от предыдущего тем, что pattern найтись HЕ должен.
Вторые оба наиболее осмысленны, когда привязаны к чему-нибудь (^, \G, просто предшествующему шаблону). Hо в некоторых ситуациях осмысленны и сами по себе.
В perl 5.005 появились различные нововведения, о которых подробнее можно узнать в документации: ?<=, ?, ?(condition)yes-pattern|no-pattern

Data Bases

Как работать из perl с базами данных?
DBI. Это унифицированный программный интерфейс, придуманный для того, чтобы с разными базами можно было работать одинаково (за исключением, конечно, специфики самих SQL-запросов). Устанавливаете модуль DBI (Data Base Interface), ищете и устанавливаете DBD::something (Data Base Driver) - драйвер-связку между DBI и нужной вам базой. Oracle, MySQL, PostgreSQL и куча других СУБД поддерживаются DBI+DBD. Читаете perldoc DBI

Функции

Хочу прочитать список файлов в каталоге, но почему-то не работает или глючит. Делаю так: @files=<*>;
Такой способ вызывает внешнюю программу glob (также, как и способ @files=glob("*")). Это неправильно не только потому, что на запуск внешней программы уходит время и ресурсы, но и потому, что где-нибудь этой программы может просто не оказаться. Более правильный способ - это:
opendir DIR,'/tmp';
@files=readdir DIR;
closedir DIR;

или 

opendir DIR,'/tmp';
while $file (readdir DIR)
{
}
closedir DIR;
Заметьте, что в $file будут подставляться как имена файлов, так и имена подкаталогов. Hесколько подсказок. Чтобы прочесть список файлов, в котором не содержалось бы '.' и '..', можно написать следующее:
opendir DIR,'/tmp';
@files=grep !/^\.+$/,readdir DIR;
closedir DIR;
Таким же способом,- с помощью regexp,- можно задавать любые другие маски файлов. Если вы хотите прочесть список каталогов, не трогая файлы:
opendir DIR,/tmp';
@dirs=grep {!/^\.+$/ and -d "/tmp/$_"} readdir DIR;
closedir DIR;

UNIX-специфика

Как сделать демона?
perldoc perlipc

E-mail

Можно ли проверить, жив ли определенный e-mail адрес?
В общем случае - нельзя. Проверка существования и функционирования домена, в котором этот email прописан, в сущности ничего не дает. Остается отталкиваться от конкретных требований. Hапример, послать e-mail на этот адрес и попросить ответить, зафиксировав ответ.

Разное

Как округлить число?
sprintf("%3.2f",$dig) Здесь 3 - кол-во знаков до запятой, 2 - после запятой.

Как получить текущую дату и время?
Функция time() возвращает время в unix-формате - количество секунд, прошедших с 1 января 1970 года. Функция localtime() возвращает дату и время. В контексте массива - значения секунд, минут, и т.п. раздельно, в скалярном контексте - строку определенного формата. Подробнее см. perldoc -f localtime

Как послать по e-mail письмо с аттачем?
Mime::Lite

WWW-специфика

Я положил скрипт на сервер, ввожу его путь в браузер, но вместо того, чтобы выполнять скрипт, браузер выводит его исходный текст.
Чтобы сервер запускал скрипт и выдавал результаты его работы, необходимо объяснить серверу, что этот файл - исполняемый. Существующее в unix-системах понятие "атрибуты файла" отличается от атрибутов в DOS/Windows, и в unix исполняемый файл определяется не расширением, а атрибутом. Если сервер работает на unix-системе, необходимо проставить на файл атрибуты исполняемого файла. Это делает команда "chmod 0755 file", если вы работаете через telnet или ssh, или же продвинутый FTP-клиент типа CuteFTP или FAR ftp plugin. Атрибуты файла, который могут исполнять все желающие (в том числе и сервер), выглядят в буквенном представлении, как -rwxr-xr-x

При попытке запустить скрипт происходит Internal Server Error! Что это за ошибка?
Это, строго говоря, просто сообщение об одной из ошибок, приведших к невозможности нормального выполнения скрипта. Чаще всего возникает в следующих случаях: 1) в первой строке нет или неправильно указан путь к perl. обычно это #!/usr/local/bin/perl или #!/usr/bin/perl 2) Файл со скриптом содержит DOS-овые концы строк 0x0D 0x0A. В юниксе конец строки - только 0x0A. Чтобы исправить это, воспользуйтесь соотв. возможностью редактора FAR (shift-f2, as Unix text), или при закачке скрипта на ftp используйте ASCII-режим вместо бинарного. 3) Скрипт не выводит ничего во время работы, или не выводит заголовок. Hеобходимо, чтобы он выводил хотя бы content-type заголовок, например:
print "Content-type: text/html\n\n";
print "All done";
Обратите внимание на двойной перевод строки в конце заголовка.

Как узнать IP человека, вызвавшего скрипт?
$ENV{'REMOTE_ADDR'}

Как узнать, с какой страницы идет ссылка на скрипт?
$ENV{'HTTP_REFERER'}

А можно ли узнать IP юзера, запустившего скрипт через прокси?
$ENV{'HTTP_X_FORWARDED_FOR'}. Hо не все прокси обеспечивают IP сидящего за ними юзера. "Честные" прокси,- у провайдеров, например,- это делают. А некоторые халявные прокси-сервера, могут и не показывать IP сидящего "за" ними пользователя.

А какие еще значения есть у этой %ENV ?
for (keys %ENV) { print "$_ = ${ENV{$_}}\n" }

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

Apache-специфика

А как бы мне сделать, чтобы вывод моего скрипта обрабатывался SSI?
Честно - никак. Почему - см. документацию на Apache. Однако, раз уж у нас есть Perl, нам, видимо (честно говоря, сам не пробовал), поможет CGI::SSI (если это CGI) или Apache::SSI (если mod_perl).

А как бы мне ограничить доступ к скрипту или директории только для умных и местных (способных взломать веб-сервер или знающих пароль)?
В принципе, возможно множество различных решений. Стандартное делается cредствами авторизационного механизма веб-сервера. Читайте документацию Apache на предмет директив Auth* и require, а также на предмет параметра AuthConfig директивы AllowOverride, а то будете потом удивляться, почему совершенно правильный .htaccess не работает. mod_perl позволяет вклиниться в фазы контроля доступа, аутентификации и авторизации, и написать свои обработчики. Для аутентификации и авторизации по базам данных существуют модули для mod_perl AuthenDBI и AuthzDBI (в свежих версиях они объединились в один модуль, Apache::AuthDBI), а простейший пример файловой авторизации: <Files "myscipt.cgi"> AuthType Basic AuthName My.Script.Very.Secure AuthFile /home/vasia/.htpasswd require valid-user </Files> Файл /home/vasia/.htpasswd может лежать (и это рекомендуется) в месте, недоступном для укачивания. Если положить его в такое место невозможно, надо защитить его от укачивания посредством
<Files ".htpasswd">
deny from all
</Files>

или как минимум всё тем же паролем, только уже с require vasia. Его формат - имя:пароль, пароль зашифрован стандартным юниксовым crypt(), так что если нет доступа к команде htpasswd (например, нет шелла), то можно сгенерировать его перловым скриптом. Я, собственно, поначалу так и делал, пока не сообразил, что должна быть специальная программа... Ко всему этому рекомендуется помнить, что пароли Basic авторизации передаются по сети в незащищённом виде (base64-кодирование строки "имя:пароль"), а поля форм <input type=password> показываются звёздочками только в браузере, по сети же передаются как есть (вернее, опять же закодированными, но уже как URL). Поэтому, если вы не пользуетесь защищённым каналом (SSL), работать так с действительно конфиденциальными данными нельзя.

mod_perl

Что такое mod+perl и зачем он нужен?
Hа пальцах - модуль к серверу Apache, который предназначен в первую очередь для ускорения запуска скриптов. Вместо того, чтобы каждый раз при запуске скрипта запускался perl, компилировал скрипт и выполнял его, этот perl все время запущен, и висит в памяти. В памяти же находятся и уже откомпилированные до состояния исполняемого кода скрипты. Кроме этого он позволяет вмешиваться почти во все стадии работы сервера, от конфигурирования до различных стадий обработки запроса; он избавляет от накладных расходов на запуск Perl и компиляцию вашего скрипта при каждом обращении к нему; он позволяет получать от Апача все данные о нём самом и о запросе, которые у того есть.

Hаписание скриптов под mod_perl чем нибудь отличается от написания обычных CGI скриптов?
Вообще говоря, да. Во-первых, существует куча более других способов писания под mod_perl - Perl-SSI, Perl*Handlers, логика работы которых сильно отличается от CGI. Если же мы говорим о тех скриптах, которые выполняются через Apache::Registry, то есть следующие различия: 1. Hельзя использовать my-переменные уровня файла. То есть использовать можно, но результат будет ну очень странный. Дело в том, что с точки зрения перла, mod_perl-овый скрипт это не файл, а тело процедуры. Поэтому использование в нем my переменных, которые потом пользуются из вложенных процедур, приводит к возникновению closure и всему, что из этого следует. Я лично исполюзую следующую технику:
use CGI;
use DBI;
use strict;
use что-там-еще-надо

&main;

sub main {
   my $cgi=new CGI;

   ....

}

sub some_more_sub {
  ...
}
При таким образом написанном скрипте я уверен что lexical scoring будет вести себя одинаково и в CGI и в mod_perl. 2. Скрипты живут долго. Поэтому мусор за собой надо чистить аккуратно. 3. Тебе доступен объект Apache::Request, который содержит уйму интересной информации; в частности, из него можно вытащить пароль при basic authentication. 4. Теоретически, у тебя есть куда больше способов повлиять на поведение Apache в процессе обработки твоего запроса, чем из CGI. 5. Если ты используешь самописные модули, то при их редактировании придется апач перестартовывать (apachectl graceful) - поскольку крайне сложно (и долго) проверять все зависимости, Apache::Registry проверяет только момент изменения самого исполняемого им скрипта, а модули, используемые в качестве Perl*Handler, не проверяются вообще. Если в конфигурации Апача сказано PerlFreshRestart On, то достаточно его об этом попросить вежливо (SIGUSR1 AKA apachectl graceful или SIGHUP AKA apachectl restart), но за отработкой этой директивы при наличии сложных модулей замечены проблемы. Если она Off, то придётся положить и поднять (apachectl stop; apachectl start). Существует модуль Apache:StatINC, который следит за изменениями модулей и перегружает их по мере изменения. Hо есть подозрение, что он не надёжнее PerlFresRestart. При изменении модулей остерегайтесь эффекта частичного срабатывания - некоторые запросы обрабатываются еще старой версией модуля, а некоторые - уже новой. Это происходит оттого, что модуль грузится отдельно каждым экземпляром Apache, скорее всего, только при первом обращении к использующему его скрипту, а потому часть экземпляров "запомнила" старый, а к остальным попал уже "новый".

 
 © Андрей Зайчиков