On-Line Библиотека www.XServer.ru - учебники, книги, статьи, документация, нормативная литература.
       Главная         В избранное         Контакты        Карта сайта   
    Навигация XServer.ru






 

Перл для чайников от NS

Часть первая

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

Эту статью я решил написать, после того как узнал насколько сложно "врубиться" во всё, даже если у вас есть под рукой какое либо пособие по PERL. Везде, уже в самом начале, начинают ссылаться на какие-то загадочные термины и команды, а вам остаётся только удивлённо хлопать глазами, или (если вы всё же что-то поняли) заставить эти программы работать (не "как надо", а вообще!). Эту статью можно было бы назвать "PERL для чайников", если бы она охватывала весь материал, но здесь я ставлю перед собой цель дать вам лишь необходимые начальные понятия, и так сказать "подготовить к дальнейшим сражениям":). Хотя вполне возможно, что в дальнейшем, "по просьбам трудящихся", эта небольшая статья разрастётся в нечто большее.

Итак... начинаем!

Для начала сообщу вам, что PERL необходимо установить на ваш компьютер. Эту, казалось бы, простую операцию некоторые мои знакомые начисто пропускали, а после, написав простенькую программу, долго пытались её запустить... ;) Наиболее доступный пакет PERL (на мой взгляд) - это ActivePerl, хотя, этот пакет ориентирован на пользователей Windows, а если у вас UNIX, то можно скачать что нибудь родное с www.perl.com. Так или иначе, вы достанете и поставите себе perl (если уже этого не сделали). Так вот: у вас появится новая папочка "perl", но это вовсе не значит, что все проги нужно помещать именно туда :) Perl, там сидящий, лишь исполняет все ваши гениальные творения с расширением *.pl , а уж где они сами находятся - одному юзеру известно :) (справедливо для пользователей windows с установленным пакетом ActivePerl, т.к. он ассоциирует файлы *.pl).

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

#!/usr/bin/perl

Всё дело в том, что язык этот создавался на базе ОС UNIX, а эту строку нам пытаются передать в "наследство" от их операционки. Однако вам следует помнить, что на сервере (если вы решите скинуть туда свои проги) может стоять и UNIX.

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

Практически все руководства по этому языку начинаются с самой простой программы, которая выглядит примерно так:

print ("hello, WORLD!\n");

Некоторые из вас уже, наверное, скопировали приведенную программу в свой файл и заметили, что она быстренько открывается и также быстро закрывается. Это связанно с тем, что программа есть программа, и после того как она выполнится - сразу же закроется, поэтому добавьте к программе ещё одну строку с следующим содержанием:

<>;

В итоге всё это примет следующий вид:

print ("hello, WORLD!\n");
<>;

... Не так уж и просто выглядит для непосвященного... Даже немного пугающе... Но это только для непосвященных, на самом деле всё - проще некуда! :) Не верится? Сейчас докажу.
Во-первых, вам нужно узнать, что print - это команда, которая выводит информацию на стандартный вывод STDOUT (STanDart OUT или, проще говоря - вывод на монитор).
Во-вторых, непонятность в виде \n - это переход на новую строку (newline), но не программы, как могли бы испугаться некоторые, а информации на экране, т.е. если бы вы продолжили бы текст, заключенный в кавычки, то после этого символа он был бы напечатан с новой строки. А если вам понадобилось бы в самом тексте использовать обратный слеш (шелс:), то перед ним надо поставить еще один шелс. Например:

print "\a";  #Команда, после которой Perl 
             #выведет сигнал на SPICER
print "\\a"; #Perl просто выведет на экран \a

Затем хочу вас обрадовать: скобки нафиг не нужны:) Их использование зависит целиком от вашего настроения, хотя в мануалах говорят, что это якобы помогает выделить текст в программе. В общем - кому как больше нравится...
Как вы уже наверно догадались - кавычки нужны для заключения в них текста, так что осталось два непонятных пунктика. Но перед тем как остановится на них, считаю необходимым объяснить вам какая бывает информация в Perl.
Фундаментальной единицей информации в Perl является скаляр (scalar), т.е. отдельное значение, хранящееся в отдельной переменной.

$a = "hello, world!"; #Присвоить переменной $a некий текст
$b = 777; #Присвоить переменной $b некое число

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

$abc = "123"; #Число в строке
$123 = 123; #Число как таковое

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

Точка с запятой в конце каждой строки - это собственно... конец строки, из чего следует, что вы можете написать всю программу в одну строку, но нам что - строк жалко что ли:) Из выше сказанного есть исключение: знак # говорит о том, что всё, что есть в строке после него - это комментарий, и к программе уже не относится.
Знак ромб <> - это по умолчанию <STDIN> или, говоря понятным языком - стандартный ввод с монитора (разъясняю: на мониторе появляется запрос, а вводите вы конечно же через клаву. Потом нажимаете ентер и введенное значение уже в переменной Perl, если она была задана). Вся хитрость добавления этого ромба в нашем случае в том, что он будет запрашивать у вас этот ввод, пока вы не нажмете кнопку "enter", а так как в программе не указанно, что делать с этим вводом, то perl о нём просто забудет и станет считать нашу программку завершенной. И врезультате выполнения этой программы мы с вами увидим на своих мониторах текст Hello, world! .

Теперь немного усложним нашу программку:

print "enter your name: ";
$name = <>;
print "hello $name!";
<>;

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

Итак, в первой строке мы выводим предложение ввести имя пользователя. Во второй строке мы его считываем в переменную $name. $name - это, как уже говорилось, скалярная переменная Perl, которая начинается знаком доллара. Забегая вперёд, скажу вам, что кроме переменных, начинающихся с доллара, бывают также массивы (@массив), хэши (%хеш), и ещё несколько видов, о которых пока рано рассказывать. Между переменной и ромбом стоит равенство, это значит, что мы присваиваем переменной результат запроса. В третьей строке мы выводим слово hello, а после него выводим то, что хранилось в переменной $name. В нашем случае это имя, которое мы просили ввести.

Сделаем ещё одно отвлечение, в котором я расскажу вам, что можно делать с переменными... С ними можно делать ВСЁ! И это не преувеличение. Например, возможно такое:

$a = 3;
$b = 4;
$c = $a+$b; #Сложить две переменные и
#присвоить их третьей
print $c; # Вывести получившееся число
print $a+$b; # тоже самое, только без
# привлечения третьей переменной

Надеюсь с этим всё понятно... А пока до некоторых доходит, мы напишем программку, которая выполняет команды ДОС dir. Для тех кто не знает - dir - команда выводящая на экран содержимое директории в которой вы находитесь.

$dos = `dir`;
print $dos;
<>;

Эта программка считывает в переменную $dos результат выполнения команды dir, которая заключена в обратные кавычки, (если бы это были простые кавычки, то получилась бы не команда, а просто слово) после чего выводит на монитор этот самый результат.

Теперь так сказать вернёмся к нашим баранам, вернее пока лишь к барашкам:) Мы научились выводить на экран необходимый нам текст, получать информацию от пользователя, а так же узнали, что ДОС команды в обратных кавычках будут выполняться как ДОС команды:) Самое время написать программку, которая будет запрашивать не что иное, как эти самые команды:

print "enter comand: ";
chmod($com = <>);
print `$com`;
<>;

Из соображений безопасности крайне не рекомендую вводить команду FORMAT, догадайтесь почему:) Из новшеств нужно выделить появление команды chmod(). Эта команда убирает из информации, которую мы получаем в запросе знак новой строки \n, который есть там по умолчанию. То, что находится во второй строке - это сокращенная запись двух строк:

$com = <>; #Считать в $com
chmod ($com); #Убрать всё лишнее

Выгадываем мы этим всего несколько символов, но ведь всё равно приятно:)

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

Часть вторая

Итак вы всё же решили встпть на тернистый путь Perl программиста и полностью испить эту чашу. Ну что ж, похвально. Тогда пришло время познакомить вас с самым главным правилом Пёрл:
"Всегда есть несколько способов сделать это!"
Может пока это для вас непонятно, но поверьте - в этом вся соль...

Ну и хватит философствовать, пора заняться делом. В предыдущей главе мы остановились на программе, которая считывает введенную дос команду, а затем её выполняет. Если вы помните - я настойчиво не советовал вам вводить дос команду format, и если вы это читаете, то наверняка вы этого не сделали. Но всегда будет опасность того, что вашу прогу запустит кто-то другой. В этом случае нам просто необходимо усовершенствовать нашу программу таким образом, чтобы при вводе команды format как минимум ничего не форматировалось. Задумаемся: как это сделать? Нам нужно посмотреть какая команда была введена, и в соответствии с этим разрешить или запретить её. Т.е. будет поставленно условие, которое будет соблюдаться при получении команды. Рассмотрим как это действует.

If (проверяем условие) {
Если всё правильно - сделать одно;
}
else {
Если нет - другое;
}

В скобках после оператора IF находится некое условие, которое в результате проверки даст нам истину или ложь. Эти два понятия являются основными для Пёрл и поэтому вам придётся смириться с их некоторой "странностью". Истиной в Пёрл является НЕ пустая строка или, если речь идёт о числах, не ноль. Результатом проверки условя и будет 1 или 0. Таким образом, если при поиске в введённой команде слово format , мы получим истину, то выполнится первое действие, заключенное в круглые скобки и называемое блоком операторов (например можно вывести строку с сообщением об ошибке) иначе выполнится второй блок операторов.

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

If (условие1) {
Первый блок операторов; }
Elsif (уловие2){
Второй блок операторов; }
Elsif (условие3) {
Третий блок; }
Else {
Четвёртый блок;}

Такая форма записи позволит вам задавать столько условий, сколько понадобится. А теперь - долгожданный апгрейд:

print "enter comand: ";
chmod($com = <>);
if ($com =~ /format/i) {
print "incorrect command\a";
}
else {
print `$com`;
}
print "Press \"ENTER\" to quit";
<>;

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

While (условие) {
Блок операторов;
}

Наверное вам это покажется смешным, но цикл - это тоже основа Пёрл :) В отличаи от условия, цикл один раз выполняет блок операторов, после чего проверяется условие. И если оно истинно, то блок выполняется ещё раз. Иногда для наглядности применяют такую форму записи:

do {
Блок операторов;
} while условие;

Словами это всё можно было бы сказать так: "Выполнять до тех пор, пока условие истинно"
Но как же быть когда нам нужно сказать примерно следующее: "Делать до тех пор пока условие не станет истинным"? В этом случае применяется оператор until. Он имеет свойства обратные while и записывается также:
untli(условие){
Блок операторов;}

Или

do {
операторы
} until условие;

Для закрепления информации приведу вам простейший пример:

print "enter number 20 or 30: ";
chmod($com = <>);
while ($com <= 50) {
$com++;
print "$com\n";}
print "Press \"ENTER\" to quit";
<>;

Хотя вам наверняка уже всё поняино, :) всё же объясню эту программу. В первой строке мы выводим приглашение ввести число от 20 до 30. Во второй - мы его считываем в переменную $com. С третьей по пятую строку мы задаем цикл условием, которое ставим так: "Верно, пока $com меньше 50", а в блоке операторов сначала прибавляем единицу к нашему числу, а затем печатаем его. Когда цикл завершится мы увидим на экране череду цифр от введенного до 50 (если было введено больше, то ничего интересного не произойдёт) и просьба нажать enter для завершения программы.

А теперь, то ради чего всё это объяснялось - очередной апгрейд:

print "enter comand:";
chomp($com = <stdin>);
$pri = $com;
$com =~ tr/A-Z/a-z/;
while ($com ne "exit"){
if ($com =~ /format/){
$bad = "$pri \- BAD COMAND! \n" x 999;
print "$bad\n";
print "enter comand:";
chomp($com = <stdin>);
$pri = $com;
$com =~ tr/A-Z/a-z/;
} else{ print `$com`;
print "enter comand:";
chomp($com = <stdin>);
$pri = $com;
$com =~ tr/A-Z/a-z/; } }
print "Press ENTER to quit";
<>;

В этой версии нашей программы мы не толоко решили стоящую перед нами задачу, но и добави кое что новое. Если бы мы ввели слово exit большими буквами (или хотя бы одна буква была большой) , то желаемого эффекта мы не получили бы. Четвертая строка переводит наше слово в нижний регистр (делает все буквы маленькими) уже упомянутым методом поиска по шаблону, о котором будет рассказано в следующей главе. Кроме того вас может заинтересовать: зачем мы копируем введенное слово из $pri в $com? Это сделано для того, что бы ичспользовать первоначальный вариант ввода позже. Например вы ввели FoRMaT, после четвёртой строки это будет просто format, но в седьмой строке мы формируем новую переменную, в которой используется первоначальный вариант, предусмотрительно нами сохраненный. Далее, в восьмой строке, и это еще одно новшество, мы выводим полученную переменную 999 раз (чтоб повадно не было! :). Остальное не должно вызвать у вас затруднений, однако если таковые возникли - повторите пройденный материал.

На этом с основами циклов и условий поконченно! В следующей главе мы изучим поиск по шаблону и выясним, почему в предпоследней версии нашей проги мы не использовали перевод символов в нижний регистр, а прога всё равно работает как надо.

На последок даю вам домашнее задание ( Взято из книги Рэндала Шварца "Изучаем Perl" ) :

Напишите программу, которая читает список чисел (каждое из которых записано в отдельной строке), пока не будет прочитано число 999, после чего программа выводит сумму всех этих чисел. (Ни в коем случае не прибавляйте 999!) Например, если вы вводите 1, 2, 3 и 999, программа должна ответить цифрой 6 (1+2+3).

Часть третья

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

В этой части я расскажу вам о ещё одной основе перл - поиск по шаблону. Данная тема является основополагающей и пожалуй единственной по которой многие программисты во всем мире используют в своей работе именно перл.

Начну немного издалека... Как вы знаете (или должны узнать) в интернете основой передаваемой инфомации является текст. С помоцью текста формируются html страницы, для осуществления интерактивности вы вводите текстовую информацию в соответствующие поля... Задумайтесь над следующим: сколько раз за всё время пользованием интернет вы заполняли различные формы? Выбирали из открывающихся списков интересующие вас темы? Иногда обработку таких данных можно осуществить с помощью JavaScript, но этот способ не всегда является применимым если речь идёт например о гостевой страничке или проверки регистрационных данных, в общем о том, что нельзя сделать на одной странице, без привлечения посторонних ресурсов. Здесь нам на помощь приходит перл, со своими богатыми возможностями по обработке текста (это и является его основной отличительной чертой и одновременно преимуществом).

Итак представим себе некоторую абстратную задачу - принять от пользователя информацию и как-то на неё среагировать. Например мы просим пользователя ввести название своего любимого языка программирования (perl естественно:) и в соответствии с этим вывести ему фразу наподобии: "Молодец! Уважаю!". М-да... опять лирика... Тем не менее давайте рассмотрим как происходит обработка информации в этом случае.

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

$enter = "perl";
if ($enter eq "perl") { #стандартное сравнение
print "Молодец!";
} else {
print "Позор!";
}

Или вместо второй строки можно написать:

if ($enter =~ /perl/)...

Казалось бы - какая разница? Однако если в первом случае мы используем стандартное сравнение, то во втором примере - поиск по шаблону. В данном случай шаблоном является

/perl/

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

Допустим, пользователь проникся особым уважением к языку перл и ввел его с большой буквы. Первый вариант нам бы тогда не подошел, нам пришлось бы создавать новое условие для поиска Perl с большой буквы:

if ($enter eq ""perl){
if ($enter eq "Perl"){...}
} else...

Но в шаблоне нам достаточно добавить модификатор i и шаблон будет вылавливать слово perl невзирая на то какими буквами оно записано:

/perl/i

Пользователь может даже ввести "pErL" и программа всё равно найдет слово.
К примеру скажу вам, что подобный трюк например на С++ занял бы не менее десятка строк.

Далее представим себе случай, когда поьзователь мало знакомый с перл ввел pearl (жемчужина) вместо perl:

/pea?rl/i

В данном примере кострукция 'a?' говорит о том что нам подходит случай с буквой 'a' или без неё. А теперь представьте как эти два условия осуществить с помощью стандартного сравнения? Страшно?

Как отдельный пример, не относящийся к нашей программе, рассмотрим замену найденных по шаблону данных. Допустим нам надо заменить в неком файле все слова 'cold' на 'heat' при этом естественно слова такие как 'colder' или 'ashcold' нам земенять ненадо. Замена с помощью регулярных выражений осуществляется в перл следующим методом:

s/old/new/;

То есть мы ищем в тексте 'old' и заменяем его на 'new'. Для нашего примера это будет выглядеть следующим образом:

s/\bcold\b/heat/gi;

Поясняю. В той части, где мы описываем фразу для поиска мы применяем ключ /b, который означает границу (начало или конец) слова. В конце у нас добавлены модификаторы g и i. С модификатором i вы уже знакомы, а g означает, что поиск надо проводить многократно. Т.е. если бы мы не поставили g, то был бы произведен поиск и замена только первого найденного cold, а остальные уже остались бы без изменения.

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

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



Литература по Perl