1995 | 1996 | 1997 | 1998 | 1999 | 2000 | 2001 | 2002 | 2003 | 2004 | Оглавление текущего номера /510, 2003 г./ | Поиск  

Perl’овка в домашнем хозяйстве

Илья Щуров Voyager, voyager@noo.ru
Опубликовано: 8.10.2003


© 2003, Журнал «Компьютерра» | http://www.computerra.ru/offline
Этот материал вы сможете найти в Интернете по адресу: http://www.computerra.ru/offline/2003/510/29312/

Все началось в далеком 1987 году, когда программисту Ларри Уоллу надоело вручную делать то, что можно автоматизировать. Так и появился язык Perl, предназначенный для обработки всевозможных log-файлов, извлечения из них полезной информации и прочих нужд сисадмина юниксовой машины. В дальнейшем он развился в нечто большее, а с приходом Интернета завоевал огромную популярность как язык написания cgi-скриптов — форумов, гостевых книг, голосований и прочих элементов интерактивности веб-сайтов. Для рядового программиста слова «Perl» и «cgi» стали практически синонимами, и большинство статей на эту тему посвящено именно веб-разработке. Многие пользователи Windows даже не догадываются, что Perl можно использовать как-то иначе. А зря! Это очень удобный инструмент, способный упростить жизнь во многих областях, даже далеких от сайтостроительства. Главное — творческий подход.

Философия

Perl — язык со странностями. Это отмечает и его автор, расшифровывая название как «Patologically Eclectic Rubbish Lister» (дословно: Патологически Эклектичный Мусорный Листер) вместо официального «Practical Extraction and Report Language» (Практичный язык для извлечения информации и составления отчетов). Если знакомиться с Perl’ом после освоения С/C++, станет немного не по себе, если же учить его в самом начале программистского пути, будет еще хуже — приобретете кучу дурных привычек, ибо, объединив в себе элементы множества других языков, Perl немного противоречив и не похож ни на что другое. Однако в этом есть и своя прелесть.

Содержание руководства по Perl, запускаемого командой perldoc.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’у. В течение нескольких минут написался скрипт, вытащивший информацию о названиях и скопировавший все в правильном виде, а мне осталось лишь с ужасом представить, сколько бы я проковырялся, вручную переименовывая сто тридцать один файл.

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.

 

Практические советы

Вверху — код простого тестового Perl-скрипта, внизу — результат его работы (редактор EditPlus 2).Несколько слов о том, где взять и как заставить работать Perl. Будучи кроссплатформной open-source-разработкой, он существует в версиях для Linux, различных Unix’ов, Mac и, конечно, Win32. Дистрибутив под Windows развивает компания ActiveState — его можно скачать с сайта www. activestate.com. После установки рекомендуется прописать каталог, содержащий файл perl.exe, в переменную окружения Path, чтобы в дальнейшем его можно было вызывать из командной строки — конечно, если этого не сделал сам установщик.
Perl — интерпретируемый язык, предназначенный в первую очередь для работы с консолью, а не с графическим интерфейсом, и с этим связаны некоторые тонкости при запуске ваших собственных программ, написанных на нем. При установке интерпретатора все pl-файлы связываются с perl.exe, и их можно запускать обычным образом — кликая по иконке. Однако при этом вы, скорее всего, ничего не увидите — быстро откроется консольное окошко, выдаст то, что сказал ваш скрипт, и тут же закроется. Чтобы этого не происходило, можно завершать все свои скрипты командой ожидания ввода <>;. Дойдя до этой строки, интерпретатор остановится, вы сможете прочитать все, что он вам наговорил, и лишь тогда позволить ему удалиться, нажав Enter.
Впрочем, есть и другие методы борьбы с закрывающимися окнами. Можно вызывать Perl из командной строки, работая в каком-нибудь файловом менеджере, который еще помнит, что это такое, — например, в FAR’е. У этого решения есть существенное преимущество: возможность использования ключей, которых у Perl’а в избытке — как и у любой другой программы, пришедшей из мира Unix. Например, с помощью ключа -e можно писать короткие программы (в одну строчку), вообще не сохраняя их в файл. Для этого достаточно набрать что-то вроде perl -e “текст вашей короткой программы”.
Используя подобные «однострочники» (one-liner), называемые также «заклинаниями», гуру Perl творят чудеса*.
Если с командной строкой вы не дружны, можно предложить еще один способ взаимодействия с интерпретатором: прикрутить его к какому-нибудь текстовому редактору. Я использую для этих целей EditPlus 2 (
www.editplus.com), который позволяет загружать различные схемы подсветки синтаксиса, создавать пользовательские панели инструментов, подключать к себе сторонние средства разработки, перехватывать выводимую ими информацию. Настроив его соответствующим образом, можно запустить редактируемый Perl-скрипт нажатием Ctrl+1, тут же увидеть выданные им сообщения, в случае ошибок одним кликом перейти к строке, в которой она возникла, и вообще значительно упростить общение с языком.
Еще одна вещь, которую необходимо знать: возможности Perl расширяются за счет установки новых модулей. Модуль — это что-то вроде библиотеки функций, предназначенных для выполнения какой-то определенной задачи. Их существует огромное количество, практически под любую стандартную задачу можно найти уже готовый модуль, и, что немаловажно, собраны они в одном месте: на сайте CPAN (Comprehensive Perl Archive Network — www.cpan. org; поиск доступен по адресу search.cpan. org). Именно там я нашел функции для чтения EXIF-информации из jpg-файлов.


* (назад)См., например, 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). Ее можно найти по этому адресу. В отличие от привычных хелпов, большинство статей написаны довольно живым, даже веселым языком — правда, английским. Но это уже мелочи.


1995 | 1996 | 1997 | 1998 | 1999 | 2000 | 2001 | 2002 | 2003 | 2004 | Оглавление текущего номера /510, 2003 г./ | Поиск  

© 2004, Издательский дом «Компьютерра» | http://www.computerra.ru
Телефон редакции: (095) 232-22-61
E-mail редакции: inform@computerra.ru