Ряд соображений по
поводу Perl
(Записки продвинутого чайника)
В данной статье речь пойдёт о таком языке как Perl. Обычно он упоминается в связи с созданием гостевых книг, форумов, чатов и прочих приложений CGI. На самом деле возможности этого языка гораздо шире и одним CGI не ограничиваются. Изначально Perl использовался в операционной системе UNIX, для которой он, собственно и был изобретён как язык создания отчётов и обработки текстов. С ростом популярности этого языка были созданы версии и для Macintosh, и для MS-DOS/Windows. Автору сих тэгов довелось иметь дело с Perl'ом на Виндовском компьютере, используя этот язык именно по своему первоначальному назначению, т.е. никаких CGI или опросных форм (я использовал различные версии среды ActivePerl фирмы Active State1). Perl сразу же увлёк и даже очаровал, несмотря на трудную для восприятия приверженность к многочисленным невербальным комбинациям метасимволов. Среди преимуществ этого языка, бросившихся в глаза при первом знакомстве, следует упомянуть следующие особенности: переменные, массивы, хэши и т.д. создаются "на лету", переменные, операторы и функции могут быть интерпретированы внутри символьной строки (имеются в виду такие конструкции как print "My name is $name", где программа выведет вместо имени переменной $name её значение). Также отсутствует жёсткая типизация: одна и та же переменная может использоваться и как строковая, и как количественная, и как имя файла, не надо отвлекаться на перевод из одного типа данных в другой. Для тех целей, с которыми я использовал Perl, да и вообще для языка обработки текстовой информации, это очень важная особенность. Я не профессионал в программировании, но хотя так или иначе имею с ним дело уже много лет, до сих пор не понял привлекательности строгой типизации для создателей компьютерных языков. Не зря кто-то сказал, что Perl сочетает в себе простоту BASIC'а и мощь C - не в последнюю очередь благодаря вышеперечисленным особенностям и сохранению процедурного синтаксиса наравне с возможностью создания классов и объектов. Далее, в Perl'е встроена изощрённейшая и ухищрённейшая система поиска, замены, перестановок и бог весть чего ещё, что делает его просто незаменимым для операций над текстом и строками (лингвисты должны оценить это как никто другой). К примеру, для перевода письменного текста в фонетическую или фонологическую транскрипцию нужно лишь немногое:
А вот как выглядит код (в качестве примера мы заменим буквы исландского алфавита á, ó, ú, é на их фонологическую транскрипцию /aU/, /oU/, /u/, /je/):
open (FILE, "isl.txt"); |
# Открытие файла # Запись содержимого в переменную # $mystring # Операция замены # Запись результата в новый файл |
Вот и все дела. Наличие встроенных многофункциональных операторов подстановки и замены
m/.../, s/.../.../, tr/.../.../ (=y/.../.../) отличает Perl в выгодную сторону от многих других языков, где вам пришлось бы создавать самому соответствующие процедуры или классы. Если вы лингвист, то, конечно же, отметите, что вышеописанный пример не всегда будет работать правильно, в частности, если нам попадаются дифтонги и диграфы, но эти трудности имеют только технический характер. К тому же, компетентный человек должен догадываться, что для абсолютно точного перевода текста в фонетическую запись одних программных средств будет недостаточно - даже почти что всемогущий Perl не умеет определять морфологические границы, что фонологу, увы, приходится постоянно учитывать и поправлять ручками...
Ещё один пример, теперь уже из совершенно другой области - создания веб-страниц. Допустим, у вас есть много html-страниц, в которых задан белый цвет фона, а вам, захотелось его поменять на зелёный! Я для этого раньше открывал такие страницы в WordPad'е и запускал текстовую замену: '<body bgcolor="#FFFFFF" ' заменить на '<body bgcolor="#008000" ' Времени это занимало не так уж много, но и его было жалко, к тому же иногда я по недосмотру пропускал файлы. А потом я догадался написать следующий сценарий на Perl'е, который это делал за какие-то секунды.
Предваряя листинг кода этой программы
сделаем следующую оговорку: допустим, наши файлы имеют однообразные имена: chapter1.htm, chapter2.htm и
всего их у нас 10 штук:
$max = 10; |
# Операция замены # Не забудьте обнулить # переменную! |
А вот ещё такой пример. Многим известна такая неприятная особенность последних версий Microsoft Word запоминать html-файлы не в формате HTML, а в XML (скажите спасибо, что не в VRML :-) ). В результате получается страница неуёмно большого объёма (а зачастую и папка с дополнительными файлами), что нежелательно именно для веб-программирования, которое всегда стремится к максимальной компактности - быстрота закачки это экономия денег клиента (изредка мне попадаются в сети страницы, созданные именно в Word'е и качаются они действительно слишком медленно). Но с этим можно справиться, преобразовав страницу из XML в HTML. Наша стратегия будет заключаться в следующем: очистить всю голову страницы (т.е. пространство между тэгами <head> и </head>), а также параметры большинства тэгов, потом стереть тэги <div>, <span>, <style>, <font> и эксклюзивные тэги XML <xml>, <o:>, <!>. Конечно, мы потеряем часть форматирования и ссылки, но выигрыш окажется более весомым, или, точнее, менее весомым - в 2 раза, а то и больше:
open (FILE, "myxml.htm"); |
# "Зачистка" тэгов. # Параметр /s # позволяет наряду с # обычными # символами вычищать # ещё и символы # новой строки. # Стирание лишних тэгов. # В их разряд попал и тэг # <font> - это связано с # тем, что Word, также как # и Frontpage, порой # грешит излишней # "щедростью" на этот # тэг. # Подпрограмма, # очищающая параметры # тэгов. # |
Один полезный совет: если вы пишите страницу на русском, то не забудьте вставить следующую строку в голову страницы после завершения её "очищения":
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251"> |
Впрочем, в любом случае вас ожидает некоторая ручная доработка страницы.
Обращает на себя внимание не только простота, с которой Perl помогает нам решить подобные задачи, но и то, что в Windows 98 отсутствуют встроенные инструменты для совершения подобных операций.
Другое дело - семейство UNIX, где используется несколько языков-оболочек (shell), предоставляющих широкий набор функций, необходимых для работы с операционной системой
- кстати, многие их особенности унаследовал
и сам Perl. Почему такие мощные средства отсутствуют в продуктах фирмы Microsoft для меня остаётся большой загадкой.3
Есть лишь MS-DOS 7.10, встроенный в Windows 98, но его shell-язык, имеется в виду командный язык bat-файлов, настолько примитивен, что в нём даже отсутствуют такие элементарнейшие вещи, как функции ввода и математические операторы, в результате чего для выполнения, к примеру, умножения двух одноразрядных чисел приходится
применять поистине героическую
изворотливость (см., напр., здесь). Вот тут-то и выясняется, насколько полезным здесь может оказаться Perl. При этом обратим внимание, что предыдущие примеры в Unix могли быть вполне выполнены имеющимися возможностями оболочки (на которой даже можно писать CGI-приложения). Теперь такая возможность появляется и у Windows благодаря способности интерпретатора Perl обрабатывать инструкции в bat-файлах при его запуске с параметром -x.
Это значит, что вызвав в bat-файле программу Perl.exe -x, вы можете передать ей команды,
заключённые в этом же bat-файле. Есть
программа pl2bat.bat (папка Perl\bin), которая
преобразует файлы Perl с расширением .pl в bat-файлы.
При этом к тексту исходной программы
добавляются следующие строки:
@echo off if "%OS%" == "Windows_NT" goto WinNT perl -x -S "%0" %1 %2 %3 %4 %5 %6 %7 %8 %9 goto endofperl :WinNT perl -x -S %0 %* if NOT "%COMSPEC%" == "%SystemRoot%\system32\cmd.exe" goto endofperl if %errorlevel% == 9009 echo You do not have Perl in your PATH. if errorlevel 1 goto script_failed_so_exit_with_non_zero_val 2>nul goto endofperl #!perl #здесь будет находиться текст исходного файла с расширением .pl __END__ |
Заметим, что поскольку мы наверняка знаем, какая у нас стоит операционная система (а именно Win98), и если мы не претендуем писать скрипты для нескольких ОС, то всю эту конструкцию можно упростить, выкинув оттуда упоминания о WinNT. В результате остаётся следующее:
@echo off perl -x -S "%0" %1 %2 %3 %4 %5 %6 %7 %8 %9 #!perl #здесь будет находиться текст исходного файла с расширением .pl __END__ |
Конечно, немножко неудобно вписывать эту внешнюю часть в каждый сценарий, но мы можем просто создать шаблон и открывать его при помощи следующей нехитрой программы doscript.bat:
@echo off |
Теперь мы запишем досовский каркас будущего Perl-сценария в файл
templ.bat и введём следующую команду: doscript myfile, в результате чего появится файл
myfile.bat, где уже будет вписана необходимая начальная информация. Конечно, вся эта морока с bat-файлами необходима только тогда, когда вы намеренно вышли из графической оболочки Windows и оперируете в MS-DOS'е. В самой Windows достаточно будет создать обычный файл Perl и его запустить. Однако раз уж мы захотели усовершенствовать именно программный язык оболочки этой операционной системы, то продолжим играться с bat-файлами, где можно совместить возможности и Perl, и MS-DOS.
Отметим, что Perl подходит для использования его в качестве shell-языка именно потому, что его не надо отдельно компилировать, т.е. преобразовывать в исполняемый exe-файл, состоящий из машинного кода. Написал себе скрипт и поручил программе-интерпретатору Perl.exe его выполнять, будь то файл с расширением .pl или .bat
- и всё, вы тут же получаете доступ к богатым возможностям Perl и его огромной библиотеке.
Можно попробовать составить специальную библиотеку таких сценариев. Не имеет смысла переопределять уже имеющиеся DOS-команды,
тем более что их можно вызывать из самого Perl'а при помощи функций
exec,system и `...`. А вот дополнить имеющиеся возможности DOS'а Perl может легко. Мне как-то понадобилось провести перепись всех файлов папки \Windows с учётом времени их последнего изменения (была одна програмка, которая после её удаления и тщательнейшей очистки реестра всё равно оставляла какие-то следы своего пребывания на диске, что давало о себе знать при её повторной установке).
В этом случае мне помогла программа listfil.bat
следующего содержания4:
@echo off |
# Подключение модулей # форматирования вывода # времени и свойств файла # Корневая директория поиска # Подпрограмма поиска имён файлов и # папок # открытие директории (первый элемент # массива аргументов @_) # перепись её содержимого в массив # закрытие директории # распечатка её полного пути # $dir = "истина" если $arr[$i] - # директория # не учитывать псевдопапки "." и ".." # занести в конец массива имён папок # иначе - в массив имён файлов # сортировка обоих массивов по # алфавиту # распечатать имена папок и файлов в # данной директории # Рекурсивный вызов процедуры # поиска для субдиректорий # Процедура перечисления папок # определение времени создания и # изменения5 # Процедура перечисления файлов # Функция, определяющая время # создания/изменения файлов/папок |
Теперь наберём команду listfil, которая в течение каких-то секунд сгенерирует файл report.log (размером порядка 400 КБ), содержащий опись всех директорий и файлов в папке \Windows со временем их создания и изменения. Фрагмент этого файла мы вам продемонстрируем:
c:\Windows |
И это всего лишь один скромный пример возможностей применения Perl'а в качестве языка оболочки операционной системы. К сожалению, в одном bat-файле можно использовать не более одного сценария Perl'а (иначе программа сбивается на бесконечный цикл, причины чего я ещё не совсем понял), однако ничто не мешает вам продолжать писать команды DOS после метки :endofperl. Как бы то ни было, уже полученные результаты должны вселять оптимизм в отношении возможности использования Perl для создания приложений под Windows.
1 Последний дистрибутив Active Perl вы можете бесплатно загрузить на
сайте этой
компании.
2 или просто скажем "в переменную", см. выше о типизации.
3 Существуют, правда,
оболочки 4Dos и 4NT фирмы JPSoftware - не очень известные
программы, я
их не пробовал, но слышал достаточно скептические отзывы. Можно ещё поставить
Cygwin - целый эмулятор Linux'а под
Windows. К слову сказать, его полная установка занимает на моём компьютере 2 ГБ (с
Apache, Х11, документацией, исходниками и т.д.) - для сравнения, объём папки \windows составляет у меня всего лишь 540 МБ. Однако ничто не мешает вам инсталлировать только основной пакет программ Сюгвина, по умолчанию указанный в установочной программе - он должен занимать гораздо меньше места. Как бы то ни было, благодаря Сюгвину вы получите доступ к большинству юникс-функций,
при том что по умолчанию они будут действовать только в
той папке, куда установлен сей диковинный зверь. Его разработчики не рекомендуют ставить его в корневую директорию диска из-за опасения совпадения названий папок у него с какой-нибудь другой программой. Я, правда, ещё ни разу не видел виндовско-досовские программы, что создавали бы в корневом разделе папки
usr, var, sbin, etc и т.д.... Но на всякий случай я при
установке последовал совету в целом глубоко уважаемых мною авторов, что, впрочем, не смертельно, т.к. к остальному дисковому пространству можно обращаться через виртуальную директорию
/cygdrive/drive_letter. Эта забавная "ОС" оказалась
хороша не только для непосредственного
обращения к юниксовским программам, но и как
учебный тренажёр команд и оболочек UNIX/Linux -
очень рекомендую!!!
4 По каким-то причинам в
Dos 7.10 отсутствует программа tree, которая,
в частности, есть в последней
самостоятельной версии ОС MS-DOS 6.22, - она
осуществляет перечисление всех папок в
указанной директории. Её отсутствие приводит
к ощутимому удлинению нашей программы.
5 Точнее, функции ctime и mtime
выдают, соответственно, время последнего
изменения индексного дескриптора файла и
время последнего изменения файла.