Часть
первая
Заранее хочу предупредить вас, что эта статья не сделает из вас
супер 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
|