![]() | |||
Илья Щуров Voyager, voyager@noo.ru
Опубликовано: 8.10.2003
Все началось в далеком 1987 году, когда программисту Ларри Уоллу надоело вручную делать то, что можно автоматизировать. Так и появился язык Perl, предназначенный для обработки всевозможных log-файлов, извлечения из них полезной информации и прочих нужд сисадмина юниксовой машины. В дальнейшем он развился в нечто большее, а с приходом Интернета завоевал огромную популярность как язык написания cgi-скриптов — форумов, гостевых книг, голосований и прочих элементов интерактивности веб-сайтов. Для рядового программиста слова «Perl» и «cgi» стали практически синонимами, и большинство статей на эту тему посвящено именно веб-разработке. Многие пользователи Windows даже не догадываются, что Perl можно использовать как-то иначе. А зря! Это очень удобный инструмент, способный упростить жизнь во многих областях, даже далеких от сайтостроительства. Главное — творческий подход.
Философия
Perl — язык со странностями. Это отмечает и его автор, расшифровывая название как «Patologically Eclectic Rubbish Lister» (дословно: Патологически Эклектичный Мусорный Листер) вместо официального «Practical Extraction and Report Language» (Практичный язык для извлечения информации и составления отчетов). Если знакомиться с Perl’ом после освоения С/C++, станет немного не по себе, если же учить его в самом начале программистского пути, будет еще хуже — приобретете кучу дурных привычек, ибо, объединив в себе элементы множества других языков, Perl немного противоречив и не похож ни на что другое. Однако в этом есть и своя прелесть.
Perl призван максимально облегчить жизнь разработчика, поэтому очень многое из того, что программист на С привык делать «руками», здесь происходит автоматически. Надоело преобразовывать переменные из строкового типа данных в числовой и наоборот? Нет проблем — в Perl’е они вообще не отличаются: все «обычные» переменные (не являющиеся массивами, файловыми дескрипторами и т. д.) имеют один и тот же тип — скалярная величина. Строка «12» может выступать в роли числа 12 и наоборот. Не надо следить за распределением памяти — если оперативной памяти достаточно, можно скопировать хоть содержимое всего Интернета в одну переменную, и не будет никаких «ошибок переполнения буфера» и связанных с ними дыр в безопасности, столь любимых хакерами всех мастей. С массивами тоже все хорошо: они меняют свой размер не менее автоматически, чем строки, и еще одной головной болью становится меньше. Хеши (или ассоциативные массивы) — это вообще сказка, ставшая былью: возможность создания наборов переменных, в которых элементы индексируются не номерами, а произвольными строками, оказалась столь удобной, что вся объектно-ориентированная часть языка построена именно на них. По сути, хеши частично заменяют структуры языка C.
Особый разговор о регулярных выражениях. Повергающие в ужас участки кода, вроде $str=~s/(\S{70})(\S+)/$1 $2/g; оказывается, являются не только нечитаемым набором символов, но и весьма удобным инструментом, позволяющим делать с текстом все, что только поддается формализации, и даже чуть больше. Если коротко, то регулярные выражения — просто средство поиска и замены участков строк, удовлетворяющих определенным шаблонам. Однако шаблоны эти могут иметь довольно сложную структуру и определять весьма нетривиальные подмножества строк. Скажем, регулярному выражению /(http:\/\/|www.)([a-zA-Z0-9-] +\.)+[a-zA-Z0-9-]{2,4}/ будут соответствовать адреса сайтов, начинающиеся с http:// или www., содержащие в себе только разрешенные символы и заканчивающиеся двух-, трех- или четырехбуквенной доменной зоной. Более того, при замене можно ссылаться на найденный текст или его участки — так, команда s/(\w+) (\w+)/$2 $1/ меняет местами пару слов, разделенных пробелом. Однако хватит о регулярных выражениях — о них написаны целые книги (например, [2]), и углубляться в подробности я не могу — места в журнале не хватит.
Во многих случаях забота о программисте в Perl’е оказалась чрезмерной. Например, отсутствие необходимости объявлять переменную перед ее использованием приводит к тому, что одна опечатка может вылиться не в сообщение об ошибке, как в C, а во многие часы отладки. Вместо того чтобы поругать невнимательного программиста, как делают другие языки, когда встречают неизвестный ранее идентификатор, Perl послушно создаст новую переменную и инициализирует ее нулем или пустой строкой (в зависимости от контекста). Понятно, что если появление такой переменной — результат опечатки, то это вряд ли входит в планы разработчика, и искать подобную ошибку придется долго. Это же относится к ряду других вещей. Впрочем, можно попросить Perl быть построже, использовав команду use strict; в самой программе и ключ -w при запуске интерпретатора — именно так рекомендуют поступать абсолютно все виденные мною руководства. Пожалуй, стоит прислушаться: усилия, затраченные на самоконтроль, многократно окупятся временем, сэкономленным на отладке.
Еще одна вещь в Perl’е, от которой у программиста с опытом работы на «обычных» языках может случиться удар — это реализация объектно-ориентированного подхода. Как такового понятия «объект» здесь вообще нет, но есть хитрым образом сконструированная его замена1. Наследование, конструкторы, деструкторы, методы и прочие атрибуты ООП — в наличии, хотя и в не совсем обычном виде. Гораздо хуже с такими вещами, как защищенные (private или protected) методы и поля данных. Они просто отсутствуют. Существуют некие соглашения о том, какие методы вызывать можно, а какие — лучше не надо, но ничего похожего на строгие правила C++ и других языков нет. Также нет никаких средств контроля типов данных. Ужас, одним словом. Но — к этому можно привыкнуть и даже полюбить.
Увы, я уже не успеваю рассказать о списках и связанных с ними контекстах, интерполяции, «умолчальных» переменных ($_ и @_), символических ссылках и многом другом. Perl — язык богатый и необычный, у него есть сотни или даже тысячи нюансов, которые можно почувствовать, только имея достаточный опыт работы. Впрочем, для применения в «домашних условиях» знать их совсем не обязательно.
1 (назад)Речь идет о Perl 5. Готовящийся к выходу Perl 6 будет полностью объектно-ориентированным языком, но это уже другая история.
Домохозяйство
Конечно, обычному пользователю обычной Windows-машины редко приходится обрабатывать log-файлы или писать cgi-скрипты, но Perl может пригодиться для решения куда более широкого круга задач. Вот несколько примеров.
Однажды мне в руки попал диск, гордо именовавшийся «Музыкальной энциклопедией Deep Purple». В действительности — обычная mp3-коллекция, немного сдобренная фотографиями, текстами песен, историей группы и кривой оболочкой. И все бы ничего, да только дать человеческие имена каталогам и файлам разработчики поленились, в результате чего mp3’шки назывались весьма загадочно: «Songs/03/02.mp3» — понятно, о какой песне идет речь? Как оказалось, информация о названиях треков хранилась, во-первых, в id3-свойствах самих файлов, а во-вторых — в лежащих в другом каталоге плей-листах. Мне же хотелось скопировать весь диск в свою музыкальную коллекцию на винчестере, но так, чтобы все было разложено по полочкам: имена файлов совпадали с названиями треков, а каталогов — с альбомами. Разбираться с id3 не хотелось, зато формат плей-листов оказался на удивление стандартным, и рука сама потянулась к Perl’у. В течение нескольких минут написался скрипт, вытащивший информацию о названиях и скопировавший все в правильном виде, а мне осталось лишь с ужасом представить, сколько бы я проковырялся, вручную переименовывая сто тридцать один файл.
Через некоторое время понадобилось перебросить часть музыкальной коллекции на карту памяти Secure Digital для прослушивания с помощью Палма. Однако выяснилось, что карманный компьютер не очень хорошо воспринимает русские имена файлов на карточке, и, недолго думая, я решил их все транслитерировать. Естественно, верный Perl был тут же вынут из ножен, написана и отлажена функция, транслитерирующая любой текст (а после отладки сохранена в надежном месте — вдруг еще пригодится), затем создан скрипт, рекурсивно ходящий по каталогам и переименовывающий все, что содержит русские буквы в своем названии. После запуска компьютер задумался. Подождав секунд двадцать, я снял приложение perl.exe, добавил в скрипт несколько строчек, выводящих отладочную информацию, запустил его еще раз и ужаснулся: из-за моей ошибки в коде он стал транслитерировать имена ВСЕХ файлов на жестком диске. К счастью, много бед наделать вышедшая из-под контроля программа не успела, но все же не могу не предупредить: «Программер, в твоих руках великая сила, поэтому будь осторожен!»
Впрочем, что я все о музыке да о музыке? Вот, например, история о применении Perl’а в фотографии. Волею судьбы на мою голову свалился цифровой фотоаппарат от Canon. При этом от удара в голове что-то повредилось, и теперь, где бы я ни находился, мой мозг автоматически анализирует окружающую обстановку на предмет композиции, освещения, выдержки, диафрагмы, баланса белого, глубины резкости и т. п., а жесткий диск компьютера постоянно пополняется гигабайтами отснятых кадров. История, которую я хочу рассказать, связана с одним из режимов работы камеры — так называемым Stitch Assist mode, который помогает снимать серии кадров для последующего их «склеивания» в одну панораму с использованием стандартного софта от Canon. Полезный режим, надо сказать. Одна проблема: чтобы скормить программе сделанные в нем снимки, их неплохо было бы для начала найти — порой среди тысяч других кадров. Не слишком интересное занятие, однако тоже легко поддающееся автоматизации. Дело в том, что камера записывает всевозможные данные о параметрах съемки в специальные EXIF-свойства файла, в том числе и режим. Поэтому достаточно взять какой-нибудь Perl-модуль, умеющий вытаскивать эту информацию (я использовал Image-Info), написать скрипт, прогоняющий через него все файлы каталога, и каким-либо образом отметить те из них, которые содержат в EXIF’е слово «Stitch». Пишется в течение пары минут!
Мне могут возразить, что можно было бы просто с помощью стандартного поиска найти все jpg-файлы, содержащие слово «Stitch» (если рассматривать их как текстовые), и не мучаться. Это, конечно, так, но с помощью скрипта можно не только выделить кадры, снятые в определенном режиме, но и, например, отсортировать их в порядке возрастания выдержки или убывания диафрагмы, или автоматически переименовать их, добавив в имя какую-то информацию о съемке, или сделать множество других полезных в хозяйстве вещей.
Еще одно занятие, для которого Perl подходит как нельзя лучше, — обработка текстов из электронных библиотек. Там часто встречаются «порезанные на строки» файлы в кодировке DOS, которые крайне неудобно печатать и читать — не из-за кодировки (ее как раз несложно перевести в Win1251), а из-за оформления: через каждые 80 символов в них начинается новая строка, а абзацы выделяются несколькими пробелами (в отличие от стандартного Windows TXT, в котором строка равна абзацу).
Борясь с подобными файлами, начинаешь ценить мощь и простоту регулярных выражений. Программа, конвертирующая их в стандартный, опрятно выглядящий HTML, занимает всего пару строчек кода. Еще пара строчек — и ее можно использовать в пакетном режиме, натравливая на целые каталоги. Долой рутину!
На десерт расскажу о совсем необычном применении этого языка. Однажды мне понадобилось проверить некоторое математическое утверждение, относящееся ко взаимному расположению многомерных эллипсоидов. Самому думать было лень, и я решил использовать для этих целей компьютер — чтоб не простаивал зря. Каково же было мое удивление, когда я обнаружил, что пишу программу не на C++ или Mathematica, а на вовсе не предназначенном для таких вещей Perl’е! Не могу сказать, чтобы результат получился изящным, но он работал. А одно из основных утверждений философии Perl так и звучит: «Если программа работает, значит, она хорошая».
Разумеется, я мог бы еще долго продолжать разговор об использовании Perl’а в самых разных «бытовых» ситуациях, но не буду — полагаю, что приведенных в статье примеров вполне достаточно, чтобы выразить основную мысль: возможность в нужный момент быстро написать программу позволяет вам решать множество нестандартных задач и дает реальную власть над компьютером и информацией. Власть, за которую не надо бороться — достаточно просто освоить Perl.
|
Практические советы
* (назад)См., например, gd.tuwien.ac.at/opsys/linux/gazette/issue90/okopnik.html. |
Литература и сетевые ресурсы
[1] С. Холзнер. Perl: специальный справочник. — «Питер», СПб, 2001. Лучшая, на мой взгляд, книга для человека, уже умеющего программировать и собирающегося изучить Perl. В свое время читал ее как художественную литературу — захватывает!
[2] Дж. Фридл. Регулярные выражения: библиотека программиста. — «Питер», СПб, 2003. Второе издание легендарной книги о регулярных выражениях.
[3] www.dklab.ru. Сайт посвящен скорее вебмастерингу, нежели Perl’у, но там можно найти много полезной информации и по языку.
[4] www.cpan.org. Очень много всего для Perl — модули, документация, дистрибутивы и т. д.
[5] www.perldoc.com. К Perl’у прилагается обширная документация, которая вызывается запуском perldoc (из командной строки) с нужным ключиком (рекомендую начать с perldoc perl). Ее можно найти по этому адресу. В отличие от привычных хелпов, большинство статей написаны довольно живым, даже веселым языком — правда, английским. Но это уже мелочи.