InfoCity
InfoCity - виртуальный город компьютерной документации
Реклама на сайте







Размещение сквозной ссылки

 

Язык программирования PERL


В главе 11 вы изучили, как создавать скрипты CGI, используя языки программирования C и C++. Однако наиболее широко применяемым языком для написания скриптов является Perl. Эта глава посвящена языку Perl и его использованию. После того как вы научитесь программировать, используя Perl, вы сможете использовать его для написания скриптов, с помощью которых решаются разнообразные задачи программирования для Internet и Web. Особый упор будет сделан на тех особенностях, которые используются при написании CGI-скриптов. Если вы никогда не программировали ранее на языке Perl, используйте эту главу как отправную точку в егоосвоении. Концепции, с которыми вы познакомитесь в этой главе, научат, как писать профессиональные скрипты на языке Perl. В главе рассматриваются не только основы программирования на Perl, но также и несколько других аспектов. К моменту окончания чтения главы вы будете в состоянии усвоить следующие ключевые концепции: Perl является интерпретируемым языком программирования, специально ориентированным на обработку текста. Программисты часто называют программы на языке Perl скриптами. Используя Perl,программисты создают CGI-формы. Perl поддерживает операции с файлами и с базами данных. Это делает его хорошо приспособленным для хранения и извлечения информации в соответствии с потребностями пользователей Web.Perl снабжается отладочной программой, с помощью которой вы тестируете код Perl.

PERL как язык программирования


Perl (Practical Extraction and Report Language) является переносимым, интерпретируемым языком, идеально приспособленным для многочисленных приложений по обработке текста. Perl поддержи вает структурированные программные конструкции, как и большинство языков программирования высокого уровня, и предлагает богат ство встроенных возможностей, накопленных им за годы эволюции среде UNIX. Perl является бесплатным программным обеспечением.Его можно получить платно, и книга <Web-программирование> служит его бесплатному распространению). Фактически, Perl версии 5 имеется, на CD-ROM, прилагаемом к этой книге. Эта глава, однако, посвящена в первую очередь концепциям Perl версии 4, которая пол ностью совместима с версией 5 и широко используется на Web.

История PERL


Отцом языка Perl является Ларри Вол (Larry Wall). Он разра ботан в 1986 году для создания отчетов о содержании многочислен ных текстовых файлов в среде UNIX. Поскольку существующие сред ства не подходили для решения такой задачи, Вол (Wall) изобрел новое средство для ее решения. Название Perl oзнaчает практичес кий язык дляизвлечения и составления отчетов (Practical Extraction а Report Language). Вол продолжал добавлять различныевозможности к Perl и сделал его доступным для общего пользования. Популярность Perl возрастает до сих пор, и он стализлюбленным средством многих программных пакетов. Умение программировать на Perl имеет возрастающую важность при составлении резюме.

PERL - интерпретируемый язык программирования


Perl является интерпретируемым языком. Это означает, чтопрограммы, написанные на Perl, обычно исполняются путем вызоваинтерпретатора Perl и переда" ему списка команд, из которых сос тоит программа. Поскольку интерпретатор тает и исполняет командыPerl именно таким образом, разработчики часто называют программына Perl скриптами. Если вы вышли из мира UNIX-систем, то, вероят но, знакомы со многими типам; скриптов, такими как скрипты shell,скрипты sed и т. д. В таком случае вы, вероятно , в состоянииоценить полезность и мощность языка, основанного на скриптах.Если вы пришли из мира DOS и Windows, то пакетные (.BAT)-файлыили программы на языке BASIC приходят на ум всякий раз, когда выдумаете об интерпретируемых скриптах. Если вы представляете себефайлы скриптов наподобие пакетных файлов MS-DOS, то вы, возможно,скептически относитесь к использованию скриптов, за исключениемсамых простейших задач. Однако если вы придерживаетесь непредвзятого взгляда на вещи, то в скором времени сможете оценить всюмощь Perl.

Сравнение PERL и языков программирования С/С++


Структура Perl очень напоминает структуру языка программирования С и на первый взгляд выглядит так же, как программа С. Всеоператоры С представлены в 1 Perl, а управляющие структуры, такие как if или for, имеются на языке Perl в несколько измененномвиде. Чего не достает в Perl, так это указателей, структур и типов, определяемых пользователем. Место языка С в программировании неоспоримо, но не следует думать, что С-программа всегда лучше, чем эквивалентная программа на языке Perl. Как и у всякогосредства, у Perl и у С есть свои области применения, к которымони лучше всего приспособлены. Надо хорошо знать оба языка, чтобы представлять, когда предпочтительнее использование одного изних.

Богатство возможностей языка PERL


Perl предоставляет разработчику широкий спектр возможностейдля создания кратких и эффективных программ. Ниже приведены некоторые наиболее замечательные черты Perl. Далее в главе вы познакомитесь с использованием каждой из них: ? Ассоциативные массивы,которые индексируются программами с использованием нецелых ключей ? Автоматическое преобразование типов между целыми числами,числами с плавающей точкой и строками ? Автоматическое преобразование размера массивов ? Функции для преобразования бинарных данных ? Широкая поддержка так называемых регулярных выражений, которые программы используют для поиска, замены и других операций,связанных с разбором текста ? Функции вывода/ввода файлов ? Функции форматированного вывода, наподобие функции С, с добавлениемк ним способности генерации отчетов на основе шаблонов (template)? Полный набор.операторов С, с добавлением также операций посравнению строк ? Функции для обработки списков, которые поддерживают стеки, очереди и другие данные списочных типов ? Функциисистемного сервиса ? Богатый набор операторов и структур управления, включая подпрограммы

Использование PERL


Чтобы разобраться, как использовать Perl, необходимо проанализировать коды написанные на нем. Самый простой путь познакомиться с языком Perl состоит в изучении коротких примеров. Следующий раздел основан на коротких примерах для того, чтобы ввести вас в курс дела. После того как вы поймете основы техникипрограммирования на языке Perl, вы сможете писать на нем CGIскрипты.

Использование PERL как фильтра данных


Средства UNIX-систем в значительной мере основаны на концепции о том, что программа служит фильтром данных, поток которыхпоступает на вход, а отфильтрованные данные - на выход. Таким образом, программа-фильтр отбрасывает нежелательные данные. MS DOSтакже поддерживает концепцию фильтра данных. Утилита grep в среде UNIX представляет собой классический пример фильтра данных.Эта утилита сканирует входной поток данных в поиске строк, которые соответствуют заданному шаблону. Программа направляет на выход те строки, которые соответствуют этому шаблону. Она отфильтровывает, отбрасывает строки, не удовлетворяющие шаблону.Perl идеально подходит для построения фильтров данных. Действительно, вы можете создать простую версию утилиты grep, используяследующий короткий скрипт на языке Perl:

   $pattern = shift(@ARGV); # берет командную строку
   while (<>)
       { # читать строку из входного потока
    print if (/$pattern/); # output line if it matches
   }

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

Использование языка PERL как шлюза безопасности


Вопросам безопасности придается большое значение как в программировании CGI, так и при решении других задач, связанных спрограммным обеспечением для сетей. Часто бывает необходимо защитить файлы и другие ресурсы системы от угрозы со стороны пользователей, которая может проистекать от их неаккуратности или дажезлого умысла. Это особенно важно для Web-серверов, а также других серверов, таких как FTP-сервер, которые подключены кInternet, где наличие злоумышленных пользователей хорошо известно. Одним из путей защиты системы от атак таких злоумышленниковслужит создание шлюзов безопасности, через которые пропускаютсявходные данные. В этом случае только данные, оцененные шлюзовойпрограммой как безопасные, передаются в систему. Традиционнобольшая часть серверов Internet исполняется под системой UNIX инаписана на языке С. Неверное использование программистами указателей на языке С ведет к нарушению безопасности работы системы.Одним из достоинств Perl, существенным при написании надежныхшлюзовых программ, служит тот факт, что переменные строкового типа изменяют свою длину автоматически в зависимости от потребности. Строковые переменные содержат столько символов, сколько имприсваивает скрипт. Perl не позволяет программе писать данные водну переменную таким образом, чтобы нарушить целостность данныхдругой переменной. Имеется также специальная версия языка Perl,которую называют taintperl, в которой осуществляется проверка зависимостей между данными и предотвращается выполнение системойкоманд по передаче данных серверу от источника, не заслуживающего доверия. Если испорченные или некорректные данные поступают навход программы taintperl, то она помечает все значения команднойстроки, переменных окружения и входные данные как испорченные,предотвращая их дальнейшую передачу серверу и возникновение фатальной ошибки.

FRONTEND-программы для связи с базой данных


Утилита типа frontend для базы данных представляет собойпрограмму, которая упрощает доступ к серверу базы данных для остальных программ. Такая программа обрабатывает запрос пользователя к базе данных и на этой основе формирует свой запрос к базе данных с параметрами, необходимыми для доступа к данным на сервере. Frontend-программа может также обрабатывать результаты запроса, формировать ответ и посылать его обратно пользователю. Как выузнаете, программисты создают простые приложения для баз данныхисключительно на языке Perl, причем не возникает необходимости вспециальном сервере базы данных. Perl имеет встроенные возможности для отображения ассоциативных массивов (обсуждаемых дальше вэтой главе) на файл базы данных. В результате доступ к файлу базы данных в рамках скрипта Perl так же прост как и доступ к элементам массива, поскольку ввод/вывод в файл является прозрачнымдля скрипта. Для более сложных приложений на основе баз данныхPerl может выполнять роль связующего звена с сервером базы данных и функционировать как Frontendпрограмма для базы данных. Несколько специальных версий языка Perl было создано для расширенияподдержки конкретных серверов баз данных. Например, oraperl обеспечивает возможность доступа к серверам баз данных Oracle.

Использование языка PERL для написания CGI-скриптов


Как вы узнали из предыдущей главы, CGI обеспечивает узламWeb вoзмoжнoсть интерактивной работы с клиентскими программами, вкачестве которых обычно выступает броузер. Во многих случаях узлы используют скрипты CGI для доступа к базам данных в тех случаях, когда клиент и сервер должны обмениваться данными.Использование CGI позволяет пользователю получать доступ к базеданных на Web, используя обычный Web-броузер. CGI-скрипт читает иобрабатывает содержание НТМL-форм, устанавливает соединение с базой данных, посылает ей запросы, обрабатывает результаты ответов,формируя на их основе новый НТМД документ, и затем посылает егообратно пользователю. Кроме того, все эти шаги должны быть сделаны так, чтобы обеспечить безопасность сервера.

Знакомство с языком PERL


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

<HELLO WORLD> на языке PERL


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

   # Три способа как сказать <Hello World>
   printf("Hello world\n");
   printf("%s\n",'Hello world');
   print "Hello World", "\n"

Первая строка представляет собой комментарий. На языке Perlзнак диез (#) означает комментарий. Когда Perl находит этот знак,он игнорирует весь текст, начиная с него и до конца строки. Знакдиез служит единственным способом ввести комментарии на языкеPerl. В отличие от С здесь нет конструкции, которая сразу бы определяла несколько строк комментариев. На первый взгляд функцияprintf выглядит так же, как в языке С. Однако вы можете заметить,что программа не содержит функции main. Хотя скрипты поддерживают подпрограммы (аналогичные функциям С), скрипт не определяетраздела, который бы содержал тело функции main. Вместо этого интерпретатор Perl сразу начинает исполнение скрипта с первого выражения в файле. Второе выражение, содержащее функцию printf,опять-таки выглядит аналогично своему использованию в языке С, заисключением того, что вторая строка аргументов заключена в одинарные кавычки ('') в противоположность двойным (""), используемым в С. В языке Perl строка в двойных кавычках означает определенный род преобразования. Например, интерпретатор Perl преобразует выражение новой строки в двойных кавычках "\n" в символ новой строки. Скрипт Perl использует одинарные кавычки для включения строковых литералов, т. е. строковых выражений, как это написано выше. Например, Perl напечатает выражение в одинарных кавычках ('\n') как два знака ('\') и 'n', а не как знак перехода нановую строку. Наконец, последняя строка кода программы содержитфункцию print, которой нет в языке С. В этом случае наиболее полезная черта этой функции заключается в отсутствии скобок. Оказывается, что вы можете всегда включать скобки в состав функцииязыка Per]. Однако в большинстве случаев необходимости в них нет.Perl требует включения скобок только в том случае, если без нихвыражение оказывается не полностью определенным, двусмысленным.Тем не менее, включение скобок в код соответствует хорошей традиции, и вам не следует отказываться от нее.

Установка PERL


Теперь настало время попробовать работать с языком Perl непосредственно. Если у вас не установлен Perl на вашей системе, тонеобходимо сделать это. Обратитесь к файлу Perl.txt на CD-ROM,который входит в комплект книги. Далее полагаем, что Perl правильно установлен. Наберите команду для запуска скрипта Perl,аналогичную следующей:

   C:\PERL>perl script-name <ENTER>

Например, создайте файл с именем hello.pl, содержащий показанную ниже строку:

   Print "Hello world\n"

Далее в командной строке наберите следующую команду:

   C:\PERL>perl hello.pl <ENTER>

На экране вы увидите следующий текст:

   Hello World

Как уже говорилось, если вы используете UNIX-систему, томожно вызвать скрипт Perl таким же образом, как другую самостоятельную программу. Для того чтобы начать, отредактируйте файлтак, чтобы первая строка была аналогична представленной ниже:

   #!/usr/bin/perl
   print "Hello world\n"

В этом случае первая строка указывает системе, что необходимо запустить скрипт, используя Perl. Можно видеть, что эта стро-ка является комментарием и это не случайно, так что Perl, проигнорирует ее. Тем не менее, большинство UNIX командных скриптовshell просмотрят два первых символа в любом исполняемом скрипте.Если первыми символами служат #!, то shell будет использовать остаток строки в качестве команды для запуска скрипта. В данномслучае такой командой является /usr/bin/perl. Shell пересдаст имяскрипта Perl автоматически. Для того чтобы запустить скрипт,необходимо запустить команду chmod для того, чтобы указать скрипту на файл, который необходимо выполнить (например, chmod + хhello.pl). В зависимости от программы shell, также может потребоваться набрать команду rehash для того, чтобы указать программеshell, что вы добавили новую команду. Возможно, также потребуется модифицировать путь к Perl, если он не инсталлирован в подкаталоге /usr/bin вашей системы.

Примечание: Большинство скриптов Perl используют в качестве расширения.р1, но это необязательно. Если вы запускаете скрипт Perlкак отдельную программу, то, возможно, более удобным будет вообще опустить расширение.

Использование отладчика PERL


Может показаться преждевременным говорить сейчас об отладчике Perl. Но использование отладчика может оказаться исключительно полезным при изучении языка Perl. С ним вы можете легкоиспытать все программы, которые приведены в этой главе в качестве примеров. Фактически можно внести любое выражение Perl непосредственно в отладчик, используя его в качестве интерактивногоPerl. Таким способом можно ознакомиться со многими возможностямиязыка, что намного проще, чем создавать и запускать полные скрипты. Отладчик Perl встроен в сам Perl. Можно запустить отладчик,используя ключ -d в командной строке следующим образом:

   C:\PERL> Perl -d hello.pl <ENTER>

В таком случае Perl загрузит скрипт hello.pl и начнет отладку. Если вы используете UNIX-систему, то можете поместить комментарий #!/usr/bin/perl -d в самом начале скрипта Perl. Если хотите загрузить Perl с отладчиком без загрузки скрипта, то можетеиспользовать следующую команду: С: \> Perl -de 0 <ENTER> В такомслучае аргумент командной строки -d указывает Perl на необходимость вызова отладчика, а аргумент -e 0 заставляет выполнить Perlскрипт, состоящий из 0 строк. Поскольку скрипт 0 не существует,то Perl просто запустит отладчик. Если Perl установлен на вашусистему корректно, то на экране вы увидите следующие данные, которые говорят, что вы находитесь в отладчике:

   Loading DB routines from $RCSfile: perldb.pl,v $$Revision: 4.0.1.3
   $$Date: 92/06/08 13:43:57 $
   Emacs support available.
   Enter h for help.
   main '(p1000159:1):
   DB<1>

Если Perl выводит ответ, но указывает на ошибку, такую какCan't locate perldb.pl @INC, то, значит, Perl установлен в вашейсистеме некорректно. В таком случае прочитайте readme-файлы, которые сопровождают вашу версию Perl. В отладчике можно набратьлюбое выражение Perl, и он немедленно его исполнит. Дополнительно можно использовать следующие команды отладчика: ? h - распечатать в качестве подсказки список команд отладчика ? n - вы-полнять до следующего выражения ? <CR> - повторить последнюю команду n или s ? p выражение - сокращение для команды print выражение ? q - окончить работу ? r - исполнять до выхода из подпрограммы ? s - один шаг по скрипту (со входом в подпрограмму)

Например, следующая команда отладчика использует функциюprint для того, чтобы вывести на экран сообщение Hello World:

   DB<1> prinf "Hello World\n"; <ENTER>
   Hello World
   DB<2>

Используя отладчик с помощью команды р, можно вывести на экран любое выражение. Для упрощения набора в отладчике можно опускать точку с запятой в конце выражения, поскольку отладчик добавит ее для вас. Наконец, отладчик всегда переходит на новую строку для новой команды. Следующий код иллюстрирует использованиекоманды р: <ENTER>

   DB<2> р "Hello World\n" <ENTER>
   Hello World
   DB<3>

Как можно видеть, всякий раз, когда вы набираете команду отладчика, счетчик отладчика увеличивается на единицу, что находитотражение в его строке DB.Читая дальше эту главу, вам, вероятно,стоит запустить отладчик, чтобы иметь возможность набирать в немпримеры и работать с языком Perl интерактивно.

Примечание: Для того, чтобы ввести выражение из многих строк вотладчик (debugger), необходимо использовать символ продолжения<\> конце каждой строки.. Иначе отладчик сообщит о синтаксической ошибке.

Следующая команда иллюстрирует использование символа продолжения при работе с отладчиком:

   DB<3> for ($i = 0; $i < 10; $i++) { \ <ENTER>
   cont: print $i; \ <ENTER>
   cont: } <EIITER>
   0123456789
   DB<4>

В этом случае для вывода чисел от 0 до 9 использовался циклfor, который будет подробно рассмотрен в этой главе.

Типы данных в PERL


Типы данных используются в программах при объявлении переменных. Короче говоря, тип данных определяет то множество значений, которые может принимать переменная, а также набор операций,которые программа может выполнять с ней. В языке Perl данные могут быть числом или строкой символов. Одно значение называетсяскалярной величиной или просто скаляром. Ниже приведены примерыскалярных значений, которые используются в языке Perl: ? Десятичные: 127 или 127.0 или 1.27Е2 ? Шестнадцатиричные: Ox7F или 0x7f? Восьмеричные: 0177 (первый 0 указывает, что используетсявосьмеричное число) ? Строка: "Hello World\n" или 'Hello World'

Например, следующая команда использует отладчик Perl для того,чтобы вывести число 0177 восьмеричной системы, соответствующеечислу 127 десятичной:

   DB<4> р 0177 <ENTER>
   127

Perl переводит данные в свой внутренний формат. Когда Perlпечатает восьмеричные или шестнадцатиричные значения, он сначалапереводит их в десятичный формат, как было показано.

Примечание: Как вы узнаете, скрипт Perl позволяет использоватьфункцию printf для того, чтобы выводить, значения в вызываемомформате, в таком как восьмеричный или шестнадцатиричный.

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

Примечание: Если вы программируете на С и использовали целочисленное деление с усечением целых чисел автоматически, то, программируя на языке Perl, надо не забыть выполнить усечение вручную, используя функцию int().

Следующая команда иллюстрирует, как Perl обрабатывает числацелого типа и с плавающей запятой:

   print 6 & 3;      # выведет 2
   print 6.9 & 3.1    #
   print 7 / 2      # выведет 2.3333    не целое
   print int(7/3)     # выведет 2

Точно так же, как Perl преобразует числа с плавающей запятой в целые числа: когда скрипт использует целочисленные значения, он также преобразует числа в строки и наоборот, когда такоепреобразование имеет смысл. Например, если скрипт использует числа в контексте, где только строки имеют смысл, например, при соединении строк, он конвертирует числа в строки. Аналогичным образом, если требуется использовать строки там, где только числаимеют смысл, то Perl конвертирует их в числа. Работая со скриптами Perl, обычно не надо беспокоиться о внутреннем представлениискалярных величин. Perl поддерживает также концепцию булевых значений, но не имеет для их описания специального типа. Как и в С,численное значение рассматривается истинным, если оно не равнонулю. Дополнительно строковое значение рассматривается как истинное, если оно не равно '' или '0'. Некоторые булевы операторы,такие как <>> (больше), возвращают единицу в качестве значения<истинно> и нуль - в качестве <ложно>. Тем самым, ваш скрипт должен просто рассматривать ненулевые величины как строчного типа,так и числового в качестве булева значения <истинно>. СкриптыPerl могут группировать скалярные величины вместе и создаватьсписок (list). Если скрипт хранит список в какой-то переменной,то эта переменная становится массивом (array).

Переменные


Perl поддерживает три типа переменных: скаляры, массивы иассоциативные массивы. Как и в языке С, имена переменных пишутсяс различением строчных и заглавных букв. Таким образом, именаVAR, Var и var описывают различные переменные. Скрипт может иметьскалярную переменную под именем var и переменную-массив, такженазванную var. Они будут различаться в языке Perl в соответствиис контекстом.

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

Скалярные переменные


Как отмечалось, скалярная переменная может содержать единственное значение. В языке Perl имена скалярных переменных всегда начинаются со знака ($). В еле дующем выражении скалярной переменной $age присваивается значение 35, а переменной $name строковое значение <Bob>. Затем используется функция print длявывода значения каждой из переменных:

   $age = 35;
   $name = 'Bob';
   print ($name,'is',$age);

Если вы сохраните эти выражения в файле под именемSCALAR.PL, то сможете запустить программу следующим образом:

   C:\PERL> Perl SCALAR.PL <ENTER>
   Bob is 35

МАССИВЫ


Как было сказано выше, массивы представляют собой переменные, принимающие в качестве значения список из скалярных величин.Следующий текст программы на языке Perl иллюстрирует объявлениепеременных типа массив и их инициализацию:

   
   @days = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat');
   print(@days);    # выведет 'SunMonTueWedThuFriSat'
   print($days[4]);       # выведет 'Thu'
   @weekdays = @days[1..5];    # значение    ('Mon','Tue','Wed','Thu','Fri')
   @emptylist = ();        #    постой список

Ссылка на переменные типа <массив> обычно начинается со знака (@) и сопровождается значениями в квадратных скобках ([ ]).Как и в программировании на языке С, индексами массивов дляскриптов всегда являются переменные целого типа, которые обычноначинаются с нулевого значения. Вы увидите исключения из этихдвух правил в примерах, которые будут объясненены в этой главе.Третье выражение ($days[4]) служит примером массива, который ссылается на скалярное значение. Поскольку он содержит только одинэлемент, результирующее значение представляет собой скаляр. Еслииспользовать знак ($) вместо знака (@), то скрипт будет ссылаться на скалярную величину. Это замечание является очень важным. Квадратные скобки указывают, что скрипт ссылается на массив.Знак $, в свою очередь, означает ссылку на скалярную величину.Инициализация массива @weekdays осуществляется путем выборки части массива @days. В предыдущем примере массив @days использовался без индекса. Когда индекс опущен, Perl ссылается на весь массив. Аналогичным образом, в предыдущем примере массив @days инициализировался списком литералов. Кроме того, что массиву могутприсваиваться в качестве значений литералы, скрипт может такжеприсваивать массивам значения переменных или даже других массивов, как показано ниже:

   @stuff = ($age, $name)
   @FriendsOfMine = ('Joe','Mary', @FriendsOfYours);

В следующем примере используются части массивов:

   @weekend = @days[0,6] ;    # результат    ('Sun','Sat')
   print (@days[1..5,0,6]);           # выведет 'MonTueWedThuFriSunSat'

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

   (@stuff >= 2) || die "Too much stuff! \n";

Функция die служит директивой языку Perl закончить выполнение и выдать при этом указанное сообщение. Если сообщение не содержится, то функция просто заканчивает выполнение скрипта. Perlтакже поддерживает специальную конструкцию $# переменная, которая возвращает последнее значение индекса в массиве. Например,следующее выражение for использует $[ для того, чтобы определитьначальное значение индекса массива, и $# для определения последнего из элементов массива. При этом с помощью выражения for выводятся значения каждого из элементов:

   for ($i =$[; $i <= $#stuff; $i++)
       {
           print $stuff[$i];
       }

Записанный цикл for можно заменить следующим эквивалентнымвыражением:

   Print @stuff;

Роль контекста для переменных скалярного и векторного типа


Отметим, что оператор построения списка (,) выглядит точнотак же, как оператор (,) последовательного вычисления (sequentialevaluation). Какой из операторов используется, зависит от контекста, в котором он появляется, в частности, является ли переменная скаляром или массивом. Perl использует конструирование списков в контексте массивов и последовательное вычисление для скаляров. Рассмотрим следующие выражения:

   @an_array = (1,2,3,4,5);
   $a_scalar = (1,2,3,4,5);

В первом выражении инициализируется массив, в то время каквторое выражение устанавливает значение скалярной переменной$a_scalar равным 5, отбрасывая первые четыре величины. Рассмотрим два следующих выражения:

   print $assoc{1,2};
   print @assoc{1,2};

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

      @x = @list;
   $x = @list;

Ассоциативные массивы


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

   $ages{'Bob'} = 35;
   $ages{'Mary'} = 25;
   $, = ' ';      # change output    separator for print operator
   print @ages{'Bob','Mary'};   #    выведет '25 35'
   print keys(%ages);       #    выведет 'Bob Mary'
   for $name (keys(%ages))
       {
           print "$name is    $ages{$keys}\n";
       }

Как можно видеть, программа присваивает значения переменной'$,' (скалярная переменная, именем которой является запятая).Скрипт использует это выражение для того, чтобы при дальнейшемиспользовании оператора print выходные данные не сливались междусобой. Далее в этой главе обсуждаются специальные переменные, такие как '$,'. Ассоциативные массивы идентифицируются с помощьюфигурных скобок. Так же как с массивами, при ссылках на ассоциативный массив целиком индексы не используются. Например, ссылка@ages{'Bob', 'Mary'} использует индексы в скобках, что указываетна ассоциативный массив. Префикс @ указывает на то, что речь идето массиве. Аналогичное использование знака доллара перед массивом указывает, что используется скалярная величина.

Примечаиие: Если два ключа заданы, то вместе со знаком @ эта говорит о том, что речь идет о части ассоциативного массива и результат должен быть в виде списка. Такое выражение эквивалентно#ages{' Bob'}, #ages{'Mary'}. которое имеет своим значением величину (35, 25).

Выражение print keys(%ages) вызывает оператор keys, которыйвозвращает полный список ключей ассоциативного массива. Ссылка %ages со знаком процента в качестве префикса означает, что ссылка относится ко всему ассоциативному массиву. Обратите внимание,что цикл for ссылается на переменные, заключенные в двойные кавычки. Наконец, последний из рассмотренных примеров также использует оператор keys и вводит цикл for для распечатки всех сочетаний ассоциативного массива. Цикл for ссылается на переменные,заключенные в двойные кавычки. Perl, в свою оче редь, заменитзначения, на которые ссылаются переменные, в то время, когда будет анализировать строку. Программисты называют этот процесс подстановкой переменной или интерполяцией.

Примечание: Perl не интерпретирует переменные, содержащие строкив одинарных кавычках.

Операторы PERL


В то время как типы данных и переменных языка Perl значительно отличаются от соответствующих типов языка С, операторы ивыражения Per] должны вам показаться гораздо более знакомыми. Всеоператоры С присутствуют в языке Perl, за исключением операторыприведения типов (type), операторы обращения к содержимому указателя *ptr и оператора выбора члена структуры var.member илиvar->member. Кроме того, в языке Perl реализовано много новыхоператоров для использования в таких операциях как сравнение иобработка строк.

Арифметические операторы


Арифметические операторы действуют на числовые значения, иих результатом является число. Если выражение включает строковыеоперанды, то Perl конвертирует строковые значения в числовые перед тем, как оценить выражение. Perl выполняет преобразованиестрок в числа подобно тому, как это делает функция atof()языка Св библиотеки времени выполнения. В настоящее время Perl поддерживает следующие арифметические операторы: ? + сложение ? - вычитание или изменение знака ? * умножение ? / деление (только для чисел с плавающей запятой) ? % взятие по модулю (только для целочисленных значений)

Рассмотрим примеры следующих арифметических операций языка Perl:

   $x = 2.5;
   $y = 3;
   print ($x + 2*$y);              # выведет 8.5
   print (7 / $y);               # выведет 2.3333333
   print int (7 / $y);             # выведет 2
   print (7 % $y);               # выведет 1
   print (7.5 % $y);              # выведет 1

Примечание: В языке Perl оператор деления всегда имеет результатом 4ucw с плавающей точкой, а результатом взятия одного числа помодулю другого является целое число и причем предварительно обаоперанда преобразуются к целому типу.

Рассмотрим следующую операцию взятия по модулю:

   print (7.9 % 3.6);       #    выведет 1 то же (7 % 3) = 1

Perl также поддерживает операторы инкремента и декремента:? ++ декремент в префиксной или постфиксной форме? - инкремент в префиксной или постфиксной формеРассмотрим примеры операций инкремента и декремента:

   $x = 4;
   ++$x;
   print $x;    # выведет 5
   $y = $x-;    # уменьшит x после присвоения    y значения x
   print "$y $x"  # выведет 5 4

Наконец, Perl обеспечивает арифметический оператор для возведения в степень (**). Рассмотрим следующие примеры использования операции возведения в степень:

   $x = 2 ** 3;     # результат 8
   $x = 2 ** 0.5;    # квадратный корень из 2
   $x = -2 ** -3;    # 1/(-2 в кубе), результат    -1/8 (-0.125)

Побитовые операторы


Побитовые операторы воздействуют на бинарное представлениецелых чисел и имеют целочисленный результат. Если операндом является строка или дробное число, Perl предварительно преобразуетего в целое число, обрабатывает операнд, используя 32-битноепредставление. Все побитовые операторы С представлены в языкеPerl: ? | побитовое ИЛИ ? & побитовое И ? ^ побитовое исключающее ИЛИ ? ~ побитовая инверсия ? << сдвиг влево ? >> сдвиг вправо

Рассмотрим следующие примеры побитовых операций:

 $x = 5;               # 101 в двоичном
   $y = 3;               # 011 в двоичном
   print $x | $y;            # 7 (111)
   print $x & $y;            # 1 (001)
   print $x ^ $y            # 6 (110)
   print $x & ~1;           # 4 (100)
   print $x << 2            # 20 (10100)
   print $x >> 1            # 2 (10)

Так же как в С, поведение операторов сдвига вправо зависит отреализации язы ка в случае, если операнд является отрицательным.

Операторы сравнения


Операторы сравнения сравнивают величины двух операндов. Также как при работе с арифметическими операторами, Perl преобразует строчные операнды в численные перед тем, как выполнять сравнение. Для того чтобы позволить скрипту сравнивать строки, которые не являются числами, Perl имеет дополнительные операторыстрокового сравнения. Эти операторы сравнивают строки, используявеличины ASCII. Если численное значение задано как операнд присравнении строк, оно сначала преобразуется в строку. Таблица 12.1перечисляет операторы сравнения:

   Число     Строка  Значение
   = =      eq       равно
   !=       nе       не равно
   >       gt       больше чем
   <       it       меньше чем
   >=       gе       больше или равно
   <=       lе       меньше или равно
   <=>      cmp      не равно (результат со знаком)

Табл. 12.1. Операторы сравнения языка PerlРезультатом операции сравнения является единица, если сравнение истинно и нуль в противном случае. Однако последняя операция (<=> или cmp) может возвращать значения -1, 0 или 1 в зависимости от того, является ли значение первого операнда меньше, чемвторого, равным ему или большим.

Примечание: Оператор cmp языка Perl ведет себя, аналогично функции Strcmp() библиотеки времени выполнения языка С.

Рассмотрим следующий пример сравнения:

   $x = 5;               # x равно 5
   print ($x < 4);        #    если false, то выведет 0

Логические операторы


Логические операторы анализируют булевы выражения и возвращают значения <истинно> или <ложно> в качестве результата. Perlобрабатывает операнды логических операций как булевы величины, т.е. как истинное или ложное значение.

Логические операторы языка Perl включают следующие:

   ? || логическое ИЛИ
   ? && логическое И

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

   ? !  логическое отрицание ()
   ? ?: условная операция
   ? ,  последовательное выполнение

Оператор логического отрицания (!) заменяет значение булевой величины на противоположную. Так же как и в С, в языке Perl условный оператор (?:) использует три операнда. Выражение, использующее условный оператор, имеет следующую форму:

 Condition ? true-result : false-result

Аналогично, следующее выражение использует условный оператор длятого, чтобы предоставить Бобу полный доступ, а всем остальным ограниченный:

   $access = ($user eq 'Bob' ? 'Full' : 'Limited');

Оператор последовательного выполнения <,> (также известный какоператор запятая) не является вполне логическим оператором, поскольку он не анализирует истинность своих операндов. Perl выполняет операнды оператора последовательного выполнения слева направо и возвращает значение самого правого операнда. Следующий пример иллюстрирует использование оператора запятая в цикле for.

   For ($i=0, $j=10; $i<10; $i++, $j-)
       {
          print i$,' ',$j
       }

Строковые операторы


Поскольку Perl представляет собой язык для обработки текста,неудивительно, что в него включены дополнительные операторы дляработы со строками. Ниже перечисляются операторы обработки строк:?. конкатенация строк ? х репликация ? =~ сопоставление переменной с образцом ? !~ то же, что и предыдущее, но с дополненным отрицанием результата

Первые два оператора легко иллюстрируются примером:

   print 'b' . 'an' x 2 . 'a';       # выведет 'banana'

Как показано, это выражение использует конкатенацию строк иоператор репли-кации для того, чтобы напечатать строку <banana>.Два последних оператора используются для проверки того, включаетли строковый операнд заданный образец. Этот вопрос детально обсуждается в разделе <Регулярные выражения>. Следующий пример иллюстрирует их использование:

   $var = 'banana';
   print ($var =~ /ana/) ? TRUE : FALSE;

В этом случае оператор проверки вхождения в строку образца(=~) использовался для проверки того, входит ли образец ana в переменную $var. В данном случае выражение принимает значение <истинно>.

Операторы присваивания


Если вы знакомы с языком программирования С, то формы операторов присваивания языка Perl должны быть для вас совершенно знакомыми. Так же как и в С, эти операторы заставляют Perl выполнить специальные операции со значениями, которые появились с правой стороны оператора, и затем выполнить присваивание:

   =   +=   -=      *=   /=   %=      |=   &=
     ^=   ~=   <<=     >>=  **=  .=      x=

LVALUES В языке Perl, так же как и в С, lvalue представляет собойимя того, что стоит с левой стороны оператора присваивания. Таким образом, lvalue представляет собой целостность, которой может быть присвоено значение, например, lvalue может быть переменной. Например, скрипт Perl не может присвоить значение строкесимволов, наподобие выражения <Bob> = 32, поскольку <Bob> не является lvalue. Тем не менее, скрипт может присвоить значение переменной $Bob, например, следующим образом $Bob = 32, посколькупеременная $Bob является lvalue. В языке Perl любая целостность,которая может использоваться как lvalue, обычно таковой и является. Например, следующее выражение упаковывает (pack) и распаковывает (unpack) список значений, причем список переменных в первомслучае и три скалярных во втором являются lvalues:

       @color = ($r, $g, $b);        # пакет цветов
       ($r, $g, $b) = @color;        # распаковка цвета

Когда вы работаете со списками в языке Perl, оператор присваивания не обяза тельно относится ко всему списку. Скрипт можетприсваивать значения отдельным элементам списка, как показано ниже:

       @items[2,4,7] = (100,200,300);

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

   ($arg1,$arg2,@rest) = @ARGV;  # можно смешать скаляры и массивы

Операции для работы со списками


В состав операций для работы со списками входят следующие:

   -  ,  конструктор списков
   -  ..  оператор области
   -  х оператор репликации

Вы уже использовали конструктор списков для инициализациимассивов и создания списка переменных, использованных какlvalues. Оператор области возвращает в качестве значения последовательность целых чисел, которая начинается от левого операнда ипродолжается до правого операнда включительно. Скрипты часто используют оператор области совместно с конструктором списков длясоздания списков. Например, следующее выражение использует оператор области для того, чтобы создать список под именем @digits,который содержит числа от нуля до девяти:

   @digits = 0..9;    # список (1,2,3,4,5,6,7,8,9)

Аналогичным образом, это выражение может использовать оператор области для создания области изменений индексов массива.Предположим, что список @days содержит дни недели (начиная с воскресенья). В следующем выражении списку @weekdays присваиваютсязначения, начиная от понедельника до пятницы:

   @weekend = @days[1..5];

Наконец, следующее выражение использует два оператора области для создания списка шестнадцатиричных цифр:

   @hex_digits = (0..9,a..f);

Оператор репликации просто создает копии данного операндауказанное число раз. Например, в следующем выражении список значений 1, 2, 3 повторяется три раза:

Операторы для работы с файлами


Perl содержит обширный список операторов для работы с файлами. Имеется не менее 27 операторов, возвращающих специфическуюинформацию о файле, даже не открывая его. Многие операторы языкаPerl ориентированы на системы UNIX, но следующие операторы работают на любых системах:

-d проверяет наличие каталога
-е определяет наличие файла
-s определяет размер файла
-w определяет, можно ли писать в данный файл

Следующие два файловых оператора возвращают булево значение.Третий оператор возвращает размер файла в байтах. Следующий текстиллюстрирует использование этих операторов:

     if (-e,'perl.exe')
        {
           print 'File size    is:' -s 'perl.exe';
        }
       else
        {
           print 'can\'    t find perl.exe\n';
        }
       (-w 'SomeFile') || die "Cannot    write to SomeFile\n";

Приоритеты выполнения операторов


Как и всякий язык программирования, Perl определяет приоритеты выполнения операторов, с помощью которых упорядочиваетсяпоследовательность их выполнения. Таблица 12.2 перечисляет приоритеты операторов начиная от высшего и следуя к низшему:

   ? ++? ! ~ унарный минус
   ? **
   ? =~ !~
   ? * / % х
   ? +? <<>>
   ? -d -е -s -w (и другие файловые операторы)
   ? <> <= >= It gt le ge
   ? = = != < => eq ne cmp
   ? &
   ? |^
   ? &&
   ? ||
   ? ..
   ?
   ? : = += -= *=

Табл. 12.2. Приоритеты операторов языка Perl от высшего к низшему

В своем скрипте вы можете изменять последовательность выполнения операторов с помощью скобок.

Конструкции языка PERL


Perl поддерживает все выражения языка С, используя почтиидентичный их формат. Например, управляющие конструкции if,while, do. for и goto используются в обоих языках в одинаковойформе. Как вы увидите в дальнейшем, оператор continue имеет несколько иное значение в языке Perl. Его прежнее значение теперьназывают next, а оператор break называют теперь last. Perl нереализует оператор switch. Кроме того, некоторые выражения языкаС можно найти в Perl в иных форматах и добавлены многие новые выражения.

Простые и составные операторы


Простым выражением называется любая допустимая комбинацияоператоров и операндов. В языке Perl оператором является выражение, заканчивающееся точкой с запятой. Как и в языке программирования С, все операторы оканчиваются точкой с запятой. Когда вывводите текст программы в отладчик, можно опускать точку с запятой, поскольку отладчик поставит ее за вас. Следующий текст иллюстрирует простой оператор присваивания на языке Perl:

       $Title = 'Web Programming';

Так же как и при программировании на С, скрипты Perl могутсодержать блоки операторов, или составные операторы, которые помещаются в фигурные скобки ({}), как показано ниже:

       {
           # Операторы
           # Другой блок операторов
       }

Ваши скрипты будут широко использовать блоки инструкций наряду с более сложными операторами. Как и в языке С, скрипты наязыке Perl могут использовать блоки инструкций для определенияобласти видимости (scope) локальных переменных. Однако определение локальных переменных в блоке не является автоматическим. Дляих декларации скрипт должен использовать ключевое слово local.Далее в этой главе мы рассмотрим область видимости переменных вдеталях.

Условные операторы


Многие предыдущие примеры использовали оператор if. В языкеPerl оператор if почти что идентичен оператору if в языке С.Отличие, однако, состоит в том, что в языке С оператор if можетиспользовать простую инструкцию без фигурных скобок, тогда как вязыке Perl инструкции обязательно должны быть заключены в фигурные скобки, образуя блок.

   if (expr)
       statement;           // приемлемо для C но не для Perl
   if (expr)
       {
           statement;     # вот так нужно делать в Perl
       }

Аналогичным образом инструкции языка Perl else работает немного отлично от соответствующей инструкции в С. В языке Perl инструкции также должны быть заключены в фигурные скобки и образовать блок:

   // Пример в С неприемлемо в Perl
   if (expr1)
       statament1;
   else if (expr2)
       statement2;
   else
       ststement3;

Ниже показано, что Perl позволяет использовать конструкциюelsif:

   if (expr1)
     {
       statament1;
     }
   elsif (expr2)
     {
       statement2;
     }
   else
     {
       ststement3;
      }

Оператор UNLESS


В языке программирования С программисты используют логическое отрицание (!) для изменения булевой величины на противоположное, как показано ниже:

   if (!(expr))      // Отрицание на С
    {
       statement;
    }

Наряду с использованием логического отрицания, скрипты Perlчасто содержат оператор unless, который обеспечивает то же самое,что и записанный выше код на С.

   unless (expr)
     {
       statement;
     }

Примечание: В отличие от языка С, Perl не содержит оператора переключения switch.

Оператор DO


Одним из частных случаев блочных операторов служит операторdo, который позволяет блоку инструкций возвращать значения. Значением, которое оператор do возвращает, является значение последнего выражения, оцененного в рамках блока. Например, следующийоператор do сравнивает строковую переменную $Month с месяцами года и присваивает переменной $DayCount значение, равное числу днейв месяце:

   $DayCount = do
    {
   if ($Month eq 'September' || $Month eq 'April' ||    $Month eq 'June' ||
   $Month eq 'November')
    {
       30;
     }
   elsif ($Month eq 'Februry')
     {
       $Year & 3 ? 28 : 29;   #    Проверка на весокосный год
     }
   else
     {
       31;
     }
         };

Обратите внимание, что Perl требует наличия точки с запятойв конце блока do. Не путайте блок do с оператором do while, который будет рассматриваться ниже в этой главе.

Циклы и ветвления


Perl поддерживает операторы циклов for, while и do с небольшими отличиями от их реализации в языке С. Существенным отличием служит то, что Perl требует использования инструкций блоками, заключенными в фигурные скобки. Кроме того, как вы познакомитесь , далее, Perl расширяет конструкцию цикла, что6ы обеспечитьее некоторые новые формы. В следующих примерах циклы for, while иdo работают аналогичным образом на языках С и Perl:

   for($i = 0; $i< 100;$i++)
    {
   printf("%d\n", $i) ;
        }
   while ($i > 0)
    {
       printf("%d\n", $i-);
    }
   do {
   printf("%d\n", $i++);
      } while ($i < 0);

Конструкция циклов на языке С отлична от конструкции на языке Perl еще и в том, что Perl не содержит оператора break, а оператор continue выполняет совершенно иную функцию. К счастью, Perlобеспечивает некоторые новые, более гибкие и более интуитивно понятные конструкции:

   ? last  выход из цикла (как оператор С break)
   ? next начать новую итерацию (как оператор С continue)
   ? redo повторить текущую итерацию

Для понимания конструкций циклов на языке Perl, необходимо разобраться с использованием блока continue. Рассмотрим следующий цикл while, который содержит блок continue:

     $i = 100;
   while ($i > 0)
    {
   print $i;
     } continue {$i-}

Вы можете представлять себе блок continue как третье выражение в цикле for, которое выполняется на каждой итерации. Аналогичным образом Perl выполняет блок continue в конце каждой итерации. Однако, как вы узнаете далее, блок continue обеспечиваетскрипту более полный контроль над процессом, чем обеспечиваетцикл for. Когда цикл на языке Perl использует оператор next, блокcontinue все равно выполняется, если только он существует. Однако если цикл использует оператор redo, блок continue не исполняется.

Метки


В скрипте Perl метки просто означают имя, соответствующеенекоему положению внутри скрипта. Имена меток оканчиваются двоеточием (например, outerloop:). Используя оператор goto, скриптможет осуществлять переходы на метку. Дополнительно могут использоваться операторы last, next и redo, для перехода к метке.Следующий код иллюстрирует использование оператора last для перехода на метку:

   outerloop: while ($i > 0)
          {
          while ($j > 0)
           {
                  #Здесь какой-нибудь другой процесс
                  if ($needToAboutLoop)
                  {
                      last outerloop;
                  }
           }
       }

В этом случае инструкция содержит ветвь last для перехода наметку outerloop и окончания выполнения цикла.

Цикл UNTIL


Еще одной конструкцией цикла в языке Perl является циклuntil, который является противоположностью циклу while. Как выпомните, в цикле while инструкции выполняются до тех пор, покавыполняется заданное условие. В цикле until, напротив, инструкции выполняются до тех пор, пока не будет выполнено условие. Например, рассмотрим цикл while, такой, как показан на следующейстранице.

     while (!(expr))
           {
                  statement;
           }

Используя цикл until, можно создать идентичный цикл, показанный ниже:

       until (expr)
       {
           statement;
       }

Аналогичным образом следующая конструкция do while использует оператор логического отрицания для того, чтобы выполнять цикл, пока заданное булево выражение не станет истинным:

   do {
       statement;
   } while (!(expr));

Используя конструкцию do until, вы можете сформировать идентичный цикл без использования логического отрицания:

   do
   {
       statement;
   } until (expr);

Циклы FOR и FOREACH


Perl поддерживает цикл for совершенно аналогично языку С:

   for (statement1; expression; statement2)
     {
       statement3;
     }

Например, следующий код использует цикл for для того, чтобывывести значения чисел от 0 до 100:

   for ($digit = 0; $digit <=100; $digit++)
     {
       print $digit, ' ';
      }

Дополнительно Perl содержит конструкцию цикла foreach, который позволяет скрипту организовывать итерации в списках и массивах. Рассмотрим пример:

   @list = ('a','b','c');
   foreach $arg (@list)
     {
       print "List item: $arg\n";
     }
   foreach $i (1..10)
     {
       print "iteration $i\n"
      }

В первом случае цикл foreach осуществлял перебор значений всписочной переменной @list. Во втором примере в цикле foreachосуществляется перебор чисел в диапазоне от 1 до 10. Внутри цикла foreach может фигурировать список, состоящий излитералов, или массив, как было проиллюстрировано в предыдущемпримере. После выполнения одной итерации циклом, специальная скалярная переменная {$arg в первом случае и $i во втором случае)принимает значение из заданного списка элементов. Область видимости этой скалярной переменной в цикле foreach ограничиваетсятелом цикла. Поэтому скалярная переменная цикла, foreach не будет конфликтовать с идентичным именем переменной, определеннойвне цикла. В следующем коде переменная с именем $i используетсявнутри и вне цикла foreach:

       $i = 1001;
       foreach $i (1..9)
         {
           print "$i\n";        # цикл выведет 123456789
         }
       print "$i\n";

Как можно увидеть из этого примера, переменная $i, используемая для организации итераций цикла, не конфликтует с переменной $i, определенной вне цикла. Особенностью цикла, foreach, которую ваши скрипты могут использовать, является возможность модификации элементов массива.(Будьте осторожны при реализации этой возможности!) Рассмотримследующий цикл foreach, который добавляет значение 10 каждомуэлементу массива:

   @list = 1..5;
   foreach $i (@list)
      {
       $i += 10;
      }
   $, = ' ';
   print @list;      # выведет 11 12 13    14 15

Сделаем несколько заключительных замечаний относительно цикла foreach. В языке Perl имена foreach и for рассматриваются каксинонимы. Поэтому в скриптах можно использовать эти имена попеременно. Perl, в свою очередь, будет определять тип цикла, основываясь на его контексте.

Оператор безусловного перехода GOTO


Perl поддерживает оператор безусловного перехода goto, который является идентичным такому же оператору языка программирования С. Ниже приведен пример использования оператора goto для вывода чисел от 1 до 10:

   $i = 1;
   loop:
       print $i++, ' ';
       if ($i <=10)
           {
                  goto loop;
           }

Модификаторы операторов


В языке Perl используются специальные формы конструкции if,unless, while и until, которые позволяют управлять ходом вычислений. В определенных случаях эти cпециальные конструкции могутсделать ваш код более ясным и легко читаемым. Для того, чтобы кодбыло легче читать и его смысл был более очевиден, целесообразновыбирать подходящий формат для записи. Рассмотрим следящее выражение, использующее функцию die для того, чтобы закончить выполнение скрипта, если значение переменной $count меньше чем 10:

   if ($count < 10)
       {
           die;
       }

Если расположить функцию die перед оператором if, как показано ниже, число строк кода уменьшится:

   die if ($count < 10);

Аналогичным образом, то же самое выражение может быть записано в следующем виде:

   ($count >= 10) || die;

В данном случае, если переменная $count больше либо равна10, Perl прекращает дальнейшее вычисление в данной строке и функция die не выполняется В противном случае, если переменная$count меньше 10, после вычисления первой части выражения код запускает функцию die и тем самым заканчивает выполнение скрипта. Наконец, в следующем примере использование конструкцииunless также позволяет уменьшить число строк до одной:

   die unless ($count >= 10);

Аналогичным образом, следующие циклы while являются идентичными:

   $i = 0;
   while ($i < 10)
     {
       $i++;
      }
   $i = 0;
   $i++ while ($i < 10);

Как можно видеть, используя модификацию конструкции, скриптпозволяет сократить число строк в записи цикла до одной. Аналогичным образом, следующие циклы until эквивалентны:

   $i = 10;
   until ($i >= 10)
     {
       $i++;
      };
   $i = 10;
   $i++ until ($i >=10);

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

Генерация динамических выражений с помощью функции EVAL


Поскольку Perl является интерпретируемым языком, ваши скрипты могут использовать Perl для того, чтобы генерировать код <налету>, то есть динамически, во время исполнения скрипта. Именнотак работает отладчик Perl (который сам является Perl-программойс именем Perldb.PL). Проектируя скрипты, вы можете использоватьтакой динамический код для создания динамических переменных именили даже построения специальных подпрограмм. Perl оценивает динамические выражения, используя функцию eval. В следующем примересоздается динамическая инструкция путем присвоения переменной вкачестве значения текста, который, собственно, и содержит требуемую инструкцию языка Perl. Дальнейшие инструкции используют функцию eval для того, чтобы выполнить эту инструкцию:

   $perl_statement = 'print "Hello, world\n";';
   eval $perl_statement;            # выведет Hello, world
   $i = 1001;
   $varname = '$i';
   print eval $varname;             # выведет значение $i

Примечание: Использование скриптом функции eval таит в себе опасности, в особенности, если скрипт передает функции eval данные,полученные от пользователя. Используя функцию eval, скрипт можетвыполнить произвольную команду языка Perl, включая даже системные команды. Это дает возможность пользователю контролироватьпрограмму, что может быть особенно рискованным для сетей Internetи Web.

Подпрограммы


Как и все структурированные языки программирования, Perl поддерживает подпрограммы. Подпрограмма может быть определена спомощью ключевого слова sub, как показано ниже:

   sub demo_sub
      {
       print "demo_sub called\n";
      }
   &demo_sub;              # вызов подпрограммы

В данном случае инструкции образуют подпрограмму, названнуюdemo_sub. Для вызова подпрограммы скрипт помещает знак амперсанда (&) перед именем подпрограммы. При вызове подпрограммы в языке Perl скобки могут быть опущены. Вы можете разместить подпрограмму где угодно в пределах исходного кода скрипта, потому что Perl проанализирует весь исходный текст перед тем, как начать выполнение скрипта. Можно объявить подпрограмму в исходном коде сразу после первого использования подпрограммы (forward reference). Подпрограммы могут иметьаргументы и возвращать значения. Следующий фрагмент кода содержит подпрограмму с именем show_value, которая выводит значение,полученное подпрограммой в качестве параметра:

       sub show_value
         {
           print 'The value    id ', $_[0];
         }
       &show_value(1001);

Формально подпрограмма языка Perl не объявляет переменныхдля хранения аргументов. Вместо этого в подпрограмму передаетсяпеременная типа массив с именем @_, которая содержит значения параметров. В свою очередь, подпрограмма получает доступ к значениям аргументов, используя следующие обозначения для элементовмассива: $_[0], $_[1], и т. д. Однако такой способ передачи параметров может ухудшать читаемость кода, и поэтому большинство подпрограмм используют копирование аргументов в локальные переменные. Аналогично предыдущему примеру, следующая подпрограммаshow_fwo_values выводит значения двух параметров:

   sub show_two_values
       {
           print 'Первый параметр    ', $_[0], "\n";
           print 'Второй параметр    ', $_[0], "\n";
       }
     &show_two_values(1001, 2002);

Наконец, следующая функция show_all_values выводит значениявсех параметров, которые она получает. Функция использует массивдля определения числа параметром:

   sub show_all_values
       {
           for ($i = 0; $i <    @_; $i++)
             {
                  print 'Parametr ', $i, ' is ', $_[$i], "\n";
             }
           }
   & show_all_values(1001,2002,3003,4004);

Как было сказано, подпрограммы Perl могут возвращать значения. Для этого используется инструкция return. В противоположность языку С, Perl не требует обязательного использования инструкции return. Если подпрограмма не содержит инструкцию return,то в качестве возвращаемого значения будет взято последнее оцененное выражение. В следующем примере складываются два параметраи возвращается результат:

   sub add_values
     {
       return $_[0] + $_[1];
     }
   print 'The result is: ', &add_values(1001,2002);

Библиотека подпрограмм


В противоположность языку С, Perl фактически не поддерживает концепцию библиотеки. Тем не менее, в нем имеется механизм,позволяющий скриптам использовать исходный код из другого файла.Например, предположим, что вы храните подпрограмму add_valuesl вфайле под именем addvalue.pl. Используя инструкцию require, другой скрипт на языке Perl может получить доступ к той подпрограмме, как показано ниже:

   require "addvalue.pl";
   print &add_values(10,11);

Вы можете представлять себе инструкцию require как аналогоператора #include препроцессора языка С. Чтобы найти файл исходных кодов, Perl сначала ищет в каталоге, определенном по умолчанию для библиотеки языка Perl (подробности можно уточнить в инструкции по инсталляции), а затем в текущем каталоге. Можно также использовать абсолютный или относительный путь, к которому добавлено имя файла. Perl запоминает, какие файлы были затребованы операторомrequire, и загружает их только один раз даже в случае многочисленных обращений к этим файлам. Имеется много стандартных библиотек, которые расширяют возможности языка Perl. Сейчас самое время побродить по каталогу, в котором хранятся библиотечные файлыязыка Perl, чтобы получить представление о тех возможностях, которые они предлагают.

Использование пакетов для изоляции подпрограмм


Если у вас имеется много подпрограмм, особенно подпрограмм,которые вы храните в различных файлах, то может возникнуть коллизия имен переменных, когда одно и то же имя переменной используется в различных целях. Perl помогает избежать этого с помощью пакетов (packages). Как известно, объявляя локальные переменные для подпрограмм, можно избежать коллизии имен. Однако если несколько подпрограмм совместно используют какие-то специфические данные, то эти данные могут потребовать глобальной области видимости, что как раз и может вести к коллизии имен.Используя пакеты, можно группировать глобальные данные в частныепространства имен (name-spaces), вне пределов которых глобальныепеременные не видны, т. е. неизвестны. Рассмотрим приведенный ниже простой пример, в котором две подпрограммы (находящиеся в различных файлах) используют частные, индивидуальные пространстваимен.

   # Код в файле one.pl
   sub sub_one
       {
           package demo_one;
           $some_data = 10;
       }
   # * * * * * * * *
   # Код в файле two.pl
   sub sub_one
       {
           package demo_two;
           $some_data = 20;
       }

Как можно видеть, первая подпрограмма использует имя пакетаdemo_one, вторая подпрограмма использует имя пакета demo_two. Обеподпрограммы могут устанавливать и использовать переменную$some_data без возникновения коллизии имен между одной и другойглобальными переменными. Скрипт <знает> имя пакета, в пределах которого находится переменная, и он организует доступ к ней, использует имя пакета вкачестве префикса к имени переменной. В следующем примере имя пакета package_one или package_two добавляется в качестве префиксак имени переменной some_data:

   &sub_one;
   &sub_two;
   print "Переменная 1 $package_one'some_data\n"
   print "Переменная 2 $package_two'some_data\n"

Когда вы используете пакеты языка Perl, можете создать уникальное пространство имен в пределах текущего файла исходных кодов путем помещения инструкции package в начале файла, как показано ниже:

   package some_package_name
   $some_data = 1;
   sub some_sub
       {
           return $some_data;
       }

В данном случае переменная $some_data существует только впакете и поэтому защищена от некорректного доступа. Использование пакета, таким образом, обеспечивает данным ту же область видимости, что и в языке программирования С, где глобальные переменные имеют своей областью видимости тот файл исходных кодов, вкотором они объявлены. При вызове подпрограммы из другого файласкриптов необходимо использовать имя пакета:

   require 'some_package.pl';
   print &some_package_name'some_sub;

Обработка строк


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

Функция CHOP


Функция chop удаляет последний символ строки. Она имеет следующий формат:

   $character = chop(Str);

Функция chop возвращает удаленный символ. Скрипты языка Perlшироко используют chop для удаления символа перехода на новуюстроку и символа конца строки.

Функция INDEX


Функция index осуществляет поиск заданной подстроки в строке. Она имеет следующий формат:

       $location = index(Str, SubStr[, Offset]);

Функция index возвращает индекс первого вхождения подстроки(SubStr) в строку (Str). Факультативно может быть задан сдвиг отначала (Offset), после которого начинается поиск. Если подстрокане найдена, возвращается значение -1. В следующем примере функция index ищет вхождения подстроки 'па' после третьего символа встроке 'banana':

           print index('banana','na',3); # Выведет 4.       


ФУНКЦИЯ RINDEX


Функция rindex ищет последнее, самое правое вхождение подстроки в строку и возвращает значение позиции первого символа подстроки. Функция имеет следующий формат:

       $location = rindex(Str, SubStr);

Эта функция аналогична функции index, за исключением того,что она возвращает последнее вхождение, а не первое. Например, вследующем примере функция rindex используется для определенияпоследнего вхождения подстроки 'na' в строку 'banana':

   print rindex('banana','na');  # Выведет 4

Функция LENGTH


Функция length возвращает число символов в строке. Она имеетследующий формат:

       $len = length(Str);

В следующем примере функция length используется для выводачисла символов в строке:

   print length('banana'); # Выведет 6

Функция SUBSTR


Функция substr используется для удаления части строки. Онаимеет следующий формат:

    $substring = substr(Str, Offset[,Len]);

Функция возвращает подстроку, т. е. часть строки, длина которой не превышает величины, заданной факультативным параметромLen. Возвращаемая подстрока строки str начинается с символа в позиции, заданной сдвигом Offset. Если параметр Len опущен, то возвращаемая строка содержит символы до конца строки включительно.Если параметр Offset отрицательный, то сдвиг вычисляется от конца строки. Наконец, скрипт может использовать substr как lvalueдля выполнения операции присваивания. Следующий фрагмент кода иллюстрирует использование функции substr.

   print substr('orange',3);   #Выведет 'nge'
   print substr('orange',-2);   # Выведет 'ge'
   print substr('orange',2,2);  # Выведет 'an'
   $str = 'apple';
   substr($str,-3) = 'ricot';
   print $str;             # Выведет 'apricot'

Примечание: Часто использование операторов языка Perl для регулярных выражений оказывается более эффективным, чем функцииsubstr. Регулярные выражения обсуждаются ниже в данной главе.

Функция JOIN


Функция join соединяет список элементов в строку, разделяякаждый элемент заданным символом. Она имеет следующий формат:

   $new_string = join(Str,List);

Функция join конвертирует каждый элемент списка в строку исоединяет строки. Следующий фрагмент кода иллюстрирует использование функции join:

   $str = join(',', 0..4,10,20); # Список будет '0,1,2,3,4,10,20'
   $strn = join ("\t", $a, $b, $c);# Смешает списки

Функция SPLIT


Функция split разделяет содержимое строки на список элементов. Она имеет следующий формат:

       split(Delimeter, Str[,Limit]);

Аргумент Delimeter определяет символ, по которому осуществляется разделение, например, пробел, слово, символ табуляции ит. д. Факультативный параметр Limit задает максимальное числоэлементов, которое может содержать список. Следующий пример иллюстрирует использование функции split.

Функции для обработки списков


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

Функция REVERSE


Функция reverse реверсирует элементы списка. Она имеет следующий формат:

    @new_list = reverse(@List);

Функция reverse реверсирует список и возвращает новый результирующий список. Следующий пример иллюстрирует использованиефункции reverse:

       @list = reverse(1..5); # Результат 5,4,3,2,1
       @list = reverse(@list); # Результат 1,2,3,4,5

Функция SORT


Функция sort сортирует элементы списка. Она имеет следующийформат:

   @new_list = sort(@List);

или

   @new_list = sort(Subroutine @List);

или

   @new_list = sort(BlockStatement @List);

Функция sort размещает элементы в списке, упорядочивая их всоответствии с порядковыми номерами символов в таблице ASCII-кодов. Так же как и функция reverse, функция sort возвращает в качестве значения новый список и не воздействует на исходный список. Следующий пример иллюстрирует использование функции sort:

   @list = sort (1,5,2,3,4);       #    Результат 1,2,3,4,5
   @list = sort(1,2,10);            # 1,10,2 сортировка в ASCII

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

   @list = sort({$a <=> $b} (2,1,10));         # @list 1,2,10
   @list = sort({$b <=> $a}) (2,1,10);         # @list 10,2,1
   sub mycomp
       {
           $b <=> $a
       }
   @list = sort(mycomp (2,1,10));     # @list    10,2,1

Функции работы с массивами


Как известно, массив представляет собой структуру данных,содержащую одно или несколько значений величин одного типа, например, 100 имен студентов. Perl содержит несколько встроенныхфункций, которые помогают работать с элементами массива. В следующих разделах рассматривается несколько основных функций дляобработки массивов.

Функции PUSH И POP


Скрипты языка Perl используют фикции push и pop для того,чтобы добавлять и удалять элементы с конца массива. Иными словами, функции push и pop позволяют скриптам выполнять операции состеком по принципу: последним вошел, первым вышел. Функция pushимеет следующий формат:

   push(@ARRAY, LIST);

Следующий фрагмент иллюстрирует использование функции push:

   @list = ();
   push(@list,10,20);       # @list    теперь (10,20)
   push(@list,1..3);       #    @list теперь (10,20,1,2,3)

В противоположность этому функция pop удаляет элемент, который был вставлен в стек последним и возвращает значение этогоэлемента. Функция pop имеет следующий формат:

   $value = pop(@ARRAY);

Следующий фрагмент программы иллюстрирует использование функции pop:

   # Возьмём @list из предыдущего примера
       print pop(@list);              # Выведет 3
       print pop(@list);              # Выведет 2
     # Теперь @list (10,20)

Функция SHIFT


Функция shift удаляет и возвращает элемент из начала массива. Эта функция аналогична функции pop с тем только отличием, чтоработает от начала массива по принципу FIFO (<первым вошел, первым вышел>). Функция shift имеет следующий формат:

   $value = shift(@ARRAY);

Следующий фрагмент программы иллюстрирует использование функции shift:

# Возьмём @list из предыдущего примера

   print shift(@list);      # Выведет    10
   print shift(@list);      # Выведет    20
       # Теперь @list ()

Функция UNSHIFT


Функция unshift добавляет один или больше элементов к началу массива. Она имеет следующий код:

   unshift(@Array, List);

Следующий фрагмент программы иллюстрирует использование функции unshift:

   # @list = ()
   unshift(@list,5,10,20);    # @list (5,10,20)
   unshift(@list, 1..3);            # @list (1,2,3,5,10,20)

Функция SPLICE


Скрипты языка Perl используют функцию splice для того, чтобы извлекать элементы из списка, заменяя их элементами другогосписка. Она имеет следующий формат:

   splice(@Array, Offset[, Count[, List]]);

Функция splice извлекает указанное число элементов {Count)из массива (@Аrraу), начиная с элемента, на который указывает величина сдвига (Offset), и заменяет элементы элементами другогосписка (List). Если в вызове функции не указан параметр Count,функция извлекает элементы до самого конца массива. Если в вызове функции не указан список, элементами которого замещаются исходные элементы, то функция не добавляет никаких элементов к первоначальному списку. Следующее выражение иллюстрирует использование функции splice:

   @list = 1..10;
   splice(@list,1,8,5,6);     # @list = (1,5,6,10)

Функция SCALAR


Функция scalar определяет число элементов в списке. Онаимеет следующий формат:

 Rsult = scalar(List);

Обычно скрипты языка Perl не нуждаются в использовании функции scalar применительно к массивам, потому что когда скрипт обращается к массиву, записывая его в скалярном контексте, то онполучает в качестве возвращаемой величины число элементов массива. Тем не менее, скрипты могут использовать функцию scalar вслучаях, когда контекст является неоднозначным или если список неявляется массивом. Следующее выражение иллюстрирует использование функции scalar.

   @list = 1..10;
   print scalar(@list);             # Выведет размер @list

Функция GREP


Функция grep фильтрует элементы списка, для которых заданное выражение принимает значение <ложно>. Она имеет следующийформат:

   @list = grep(Expression, List);

Функция grep просматривает элементы списка, подставляя их вкачестве аргумента в заданное выражение. Функция grep присваивает текущее выражение элемента списка переменной $_ и вычисляетзаданное выражение. Если полученное выражение является истинным,то функция grep добавляет этот элемент к результирующему списку.Следующий фрагмент программы иллюстрирует использование функцииgrep:

   @list = grep($_ & 1, 1..10);      #    @list (1,3,5,7,9)
   @list = ('a', '' 'b');            # @list ('a',' ','b')
   @list = grep($_ eq '', @list);     #    @list ('a','b')

Примечание: Если выражение, модифицирует переменную. $_, то исходный список также будет модифицирован.

Функции обработки ассоциативных массивов


Как известно, ассоциативные массивы - это такие массивы, укоторых индексом является не числовая величина, а, например, имя.В языке Perl имеется несколько встроенных функций, которые упрощают обработку скриптами ассоциативных массивов.

Функция KEYS


Функция keys возвращает значения ключей, которые отвечаютассоциативному массиву. Она имеет следующий формат:

   @key_list = keys(%Array);

Функция keys возвращает массив ключей в виде регулярногосписка. Следующий фрагмент программы иллюстрирует использованиефункции keys:

   $ages{'Bob'} = 25;
   $ages{'Mary'} = 30;
   $ages{'Zack'} = 15;
   @list = keys(%ages);  # @list будет 'Zack',    'Bob', 'Mary'
   @list = sort keys %ages # @ list 'Bob', 'Mary',    'Zack'
   for $key    (sort keys %ages)
       {
           print "$key is    $ages{$key}\n"
       }

Функция VALUES


Функция values возвращает обычный массив, состоящий из значений ассоциативного массива. Она имеет следующий формат:

   @value_list = values(%Array)

Функция values возвращает массив значений ассоциативногомассива в виде регулярного списка. Следующий фрагмент программыиллюстрирует использование функции values:

       # Используем значения из предыдущего примера
       %ages = ('Bob', 25, 'Mary',    30, 'Zack', 15);
       @list = sort values %ages;          # @list (15, 25, 30)
       @list = %ages;   # @list ('Zack', 15, 'Bob',    25, 'Mary', 30)

Функция EACH


Функция each осуществляет итерации элементов в ассоциативном массиве. Она имеет следующий формат:

       @key_values = each(%Array);

Всякий раз, когда скрипт вызывает функцию each, она возвращает список из двух компонент, которые содержат пару ключ-значение. Когда функция достигает конца списка, она возвращает пустойсписок. При следующем вызове функции процесс итерации начнетсясначала. Следующий фрагмент программы иллюстрирует использованиефункции each:

   # Используем значения из предыдущего примера
   %ages = ('Bob', 25, 'Mary', 30, 'Zack', 15);
 while (($name, $age) = each %ages)
       {
           # Выведем ages
           print "$key is    $ages{$key}\n";
       }

Функция DELETE


Функция delete удаляет элементы ассоциативного массива. Онаимеет следующий формат:

   Delete $Array{Key}

Следующая инструкция использует функцию delete для того,чтобы удалить элемент, отвечающий ключу Bob из ассоциативногомассива $Employees:

       Delete $Employees{'Bob'}

Аргументы командной строки


Скриптам на языке Perl легко получить доступ к аргументамкомандной строки. Всякий раз, когда запускается скрипт, Perl помещает аргументы командной строки скрипта в списочную переменную@ARGV. Следующий фрагмент программы служит для вывода аргументовкомандной строки на дисплей:

   while ($arg = shift @ARGV)
       {
           print "$arg\n";
       }

Доступ к переменным окружения


Доступ к переменным окружения осуществляется в скриптах наязыке Perl также очень просто. Всякий раз при запуске скриптаPerl помещает копии переменных окружения в ассоциативный массив сименем %ENV. В следующей инструкции массив %ENV используется длявывода текущего каталога:

   print "$ENV{PATH}\n";        # Выведет текущий каталог

Кроме получения значений из массива %ENV, скрипты также могут изменять элементы массива. Такие изменения массива %ENV изменят установку переменных окружения для всякого процесса-потомка,создаваемого скриптом. Например, следующая инструкция используетмассив %ENV для изменения текущего пути:

   $ENV{PATH} = 'c:\\myexec;'.$ENV{PATH};

Примечание: Изменения, которые скрипт делает в массиве %ENV, неповлияют на исходные переменные окружения. Иными словами, послеокончания работы скрипта переменные окружения системы не изменятся.

Файловый ввод и вывод


Perl специально разрабатывался для того, чтобы служить адекватным средством для чтения и записи в текстовые файлы. Тем неменее, как вы узнаете далее, Perl выполняет функции по произвольному доступу и вводу-выводу бинарных файлов. Операции по работе с файлами требуют указатель файла (file handle), который является переменной, соответствующей конкретному файлу. По умолчанию каждый скрипт на языке Perl имеет три стандартных указателя,которые Perl автоматически открывает при запуске скрипта: STDJN,STDOUT, STDERR. Эти три стандартных указателя отвечают стандартным потокам STDIN, STDOUT, STDERR языка программирования С. Кроме того, скрипт языка Perl может открыть дополнительные указатели для других специфических файлов.

Открытие файлов и других потоков


Для того чтобы скрипт использовал файл, он должен вызватьфункцию open. Она имеет следующий вид:

   open(FileHandle[, FileName])

В отличие от функции open библиотеки времени выполнения языка С, функция open языка Perl не содержит параметра mode в вызове функции. Perl определяет режим (mode) открытия файла, основываясь на имени файла. Таблица 12.3 иллюстрирует связь режима открытия файла и имени файла.

Табл. 12.3. Соглашение об именах и режимах доступа файлов языкаPerl
Имя файла Операция
<FILE> Открыть файл только для чтения (аналогично <r> функции fopen)
<<FILE> Открыть файл для чтения (то же самое, что <FILE>)
<>FILE> Создать файл для записи (как <w> функции fopen)
<>>FILE> Открыть файл для добавления в его конец (как <г+> функции fopen)
<+>FILE> Создать файл для чтения/записи (как <rw> функции fopen)
<+<FILE> Открыть файл для чтения/записи (как <rw+> функции fopen)
<| CMD> Открыть канал из процесса, исполняющего команду <CMD>
<CMD |> Открыть канал процессу, исполняющему команду <CMD>

Примечание: Режим канального (pipe) потока может существовать не
на всех системах.

Если в вызове функции open опущено имя файла, то Perl подразумевает, что имя файла содержится в строковой переменной$FileHandle. Когда скрипт завершил использование файла, он закрывает его, используя функцию close, как показано ниже:

       close(FileHandle);

фрагмент программы иллюстрирует использование функций open иclose:

    open(InFile, "test.dat") || die;     # открываем для чтения
                          # test.dat
    open(OutFile, ">test.dat") || die;    # создаём test.dat
    $AuxFile = ">>test.dat";
    open(Aux, $AuxFile) || die;        # открывает для дополнения
                          # test.dat
    close(InFile);
   close(OutFile);
    close(Aux);

Обратите внимание, что указатели файлов не имеют обычных односимвольных префиксов. Как вы узнаете далее, скрипты языка Perlмогут хранить имена указателей в виде строк скалярных переменныхи передавать указатель любой функции, которая может их обрабатывать. При необходимости Perl выполняет конвертацию значений. В операционной системе MS-DOS Perl поддерживает дополнительную функцию, которая называется hinmode и позволяет файловому вводу/выводу переключаться между текстовым и бинарным режимами. В большинстве же систем различие между текстовым и бинарнымрежимами не имеет значения. Однако для операционной системыMS-DOS символ новой строки представляет собой последовательностьиз двух символов (CR+LF). Поскольку большинство программ не ожидают встретить два символа в конце строки, то система ввода/вывода должна выполнить преобразование. Для того чтобы можно было использовать функцию binmode, соответствующий указатель может бытьоткрыт. Функция binmode имеет следующий формат:

   binmode(FileHandle);

Построчное чтение и запись данных


Простейшим способом для чтения скриптом строки из файла служит использование оператора <FILEHANDLE'>. В языке Perl указатель файла, окруженный треугольными скобками, становится символом ввода (input-symbol). Например, следующий фрагмент программыиллюстрирует использование символа ввода для чтения и вывода наэкран содержимого файла Test.dat.

   open(InFile, "Test.dat") || die;
   while ($line = <InFile>)
       {
           print $line;         # Выведет строку из файла
       }
   close(InFile);

Когда символ ввода достигает конца файла, он возвращает значение false, которое в данном случае заканчивает выполнение цикла while. Существует специальный (пустой) символ ввода, обозначаемый <>, который имеет весьма специальное, но полезное применение. В первый раз, когда скрипт использует пустой символ ввода<>, он анализирует аргументы командной строки. Если строка @ARGVявляется пустой, то входной символ <> читает из STDIN. Если вместо того @ARGV не пуста, то Perl открывает первый из файлов, указанных в переменной @ARGV, и читает содержимое файла. Когда Perlзаканчивает обработку одного файла, он приступает к следующему.После того как скрипт прочитал все файлы, символ <> возвращаетзначение false. Скрипты языка Perl также могут использовать символ ввода длячтения всего содержимого файла в массив так, что каждая строкафайла становится элементом массива. Например, следующая инструкция читает из файла STDIN в массив @lines:

   @lines = <STDIN>;

Запись данных в файл также достаточно проста. Фактически выэто делали всякий раз, когда использовали функцию print. Полныйформат функции print имеет следующий вид:

          print [FileHandle]   List;

Если функция print не получает в качестве аргумента указателя файла, то она посылает вывод в STDOUT. Следующий фрагментпрограммы иллюстрирует использование функции print для добавления данных в выходной файл:

       open(LogFile, '>>logfile.dat') ||    die;
       ##############
       ($m, $d, $y) = (localtime(time)) [4,3,5];
       print LogFile "Captain's log, Stardate    ++m$/$d/$y\n";
       close(LogFile);

Примечание: Указатель файла и выходной список не разделяются запятой.

Чтение и запись блоков данных


Программисты часто рассматривают текстовые файлы как текстовые потоки просто потому, что один символ следует за другим домаркера конца файла. Если скрипт должен работать с файлом, который ориентирован на работу с блоками, а не потоками, то скриптможет использовать функции sysread и syswrite для обработки фиксированных блоков данных. Функции sysread и syswrite имеют следующие форматы:

   $result = sysread(FileHandle, $Var, Length[, Offset]);
   $result = syswrite(FileHandle, $Var, Length[, Offset]);

Если в вызове функций указывается сдвиг от начала файла(Offset), то функции выполнят поиск места, с которого они начнутоперации ввода/вывода. Функции sysread и syswrite обе передаютданные, используя скалярную переменную строкового типа. Поскольку функции обрабатывают фиксированные блоки памяти, то данные могут содержать бинарные значения, включая нули и маркерыконца файла. Если в вызове функции указывается сдвиг от началафайла (Offset), то функция выполняет поиск места в файле, с которого начинает выполнять операции ввода/вывода. Если вы работаете с блоками данных, то скрипты могут такжеиспользовать следующие функции ввода/вывода:

 $result = seek(FileHandle, Position, Base);
   $result = tell(FileHandle);
   $result = eof(FileHandle);

Функция seek работает в точности так же, как fseek - функция библиотеки времени выполнения языка С. Параметр Position задает позицию относительно начала отсчета, которая в свою очередьзадается параметром Base следующим образом:

   ? 0 Поиск от начала файлов
   ? 1 Поиск от текущей позиции
   ? 2 Поиск от конца файла

Функция tell языка Perl работает в точности так же, как фикция ftell библиотеки времени выполнения языка С. Эта функция возвращает текущую позицию в файле, с которой выполняются операциичтения или записи. Наконец, функция eof, так же как и функцияfeof языка С, возвращает значение <истинно> или <ложино>, которое скрипт может использовать для определения достижения концафайла.

Обработка бинарных данных


Хотя Perl ориентирован в первую очередь на обработку текста,он также может обрабатывать бинарные данные. Скрипты могут перемещать бинарные данные частями, используя строковые переменные, ивыполнять байтовые операции ввода/вывода, используя функцииsysread и syswrite. Однако для того, чтобы выполнить что-нибудь<полезное> с данными, скрипт вынужден конвертировать данные всвои <родные> скалярные форматы.

Хранение бинарных данных


Когда скрипт на языке Perl читает блок бинарных данных, используя функцию sysread, он помещает эти бинарные данные в скалярную строковую переменную. Perl не заботится о том, что это заданные, содержат ли они нули или значения, не являющиесяASCII-символами. В пределах символьной строки Perl принимает байты как байты. В отличие от языка С, Perl не использует строк,оканчивающихся нуль-символом. Если данные соответствуют кодовойтаблице ASCII, то скрипт может их обрабатывать, как любой текст.Но если данные представляют собой бинарные величины, то скриптобязан распаковать их перед тем, как Perl сможет обработать этиданные.

Распаковка строк бинарных данных в переменные языка PERL


Для того чтобы скрипт получил доступ к бинарным данным, ондолжен распаковать их, перейдя в свой скалярный формат. СкриптыPerl распаковывают данные, используя функцию unpack, котораяимеет следующий формат:

   $result = unpack(Template, Expression);

Expression является обычной строковой переменной, котораясодержит бинарные данные, прочитанные функцией sysread, но можетбыть также выражением, которое необходимо интерпретировать какстроку. Template представляет собой символьную строку-шаблон,описывающую, как интерпретировать значения в операнде Expression.Следующий фрагмент программы иллюстрирует использование функцииunpack:

   ($r, $g, $b) = unpack("C3", $color);# распакует в 3 символа
@longwords = unpack("L*", $data); # распакует в список длинных # слов @stuff = unpack("S2L", $bin); # распакует в 2 shorts и long

Каждый символ шаблона может сопровождаться числом, указывающим, сколько раз использовать этот символ. Если вместо числастоит звездочка (*), то операция будет выполняться для всех остающихся данных в строке. Если число не поставлено, то она выполняется однократно. Скрипт может поместить любое число символовшаблона в строку Template. В таблице 12.4 перечисляются символы,входящие в строковый параметр Template вместе с описанием влияния каждого из них на выполнение функции unpack.

Табл. 12.4. Символы шаблона
Символ шаблона Описание
a Строка ASCII без нулевого символа
А Строка ASCII без нулевого символа
b Битовая строка (младший бит идет первым)
В Битовая строка (старший бит идет первым)
с Однобайтовый символ со знаком
С Однобайтовый символ без знака
d Значение с плавающей запятой, двойной точности
f Значение с плавающей запятой, одинарной точности шаблона
h Строка шестнадцатиричных значений (младшие разряды идут первыми)
Н Строка шестнадцатиричных значений (старшие разряды идут первыми)
i Целое со знаком
I Целое без знака
l Целое со знаком типа long
L То же, только без знака
n Короткое целое
N Длинное целое
p Указатель на строку
s Короткое целое со знаком
S Короткое целое без знака
u Раскодировка строки
v Короткое целое
V Длинное целое
x Пропустить вперед один байт
X Пропустить назад один байт
@ Перейти на указанную позицию в строке

Упаковка данных в бинарные строки


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

   $result = pack(Template, List);

Следующий фрагмент программы иллюстрирует использование функции pack:

   $color = pack("C3", $r, $g, $b);
   $data = pack("L*", @longword);
   $bin = pack("S2L", @stuff);

Функция pack использует те же самые символы шаблона, что ифункция unpack, за исключением символов а. А, и, х, X, @.

Работа с каталогами


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

Открытие, чтение и закрытие каталогов


Скрипты на языке Perl позволяют открывать и читать содержимое файлов. Точно так же эти скрипты открывают каталоги и читаютимена содержащихся в них слайдов. Для открытия каталога скриптыиспользуют функцию opendir, передавая указатель каталога и путь кнему. Для чтения списка файлов, содержащихся в каталоге, скриптиспользует функцию readdir. Наконец, для закрытия каталога используется функция closedir. Следующий фрагмент программы иллюстрирует использование функции readdir для того, чтобы вывести наэкран список файлов в текущем каталоге:

   opendir(Dir, $INC[2]) || die;
   while ($file = readdir(Dir))
       {
           print "$file \n"
       }
   closedir(Dir);

В этом фрагменте используется переменная $INC[2J для доступа к текущему каталогу. Изменяя $INC[2] на $ARGV[0], скрипт выводит на экран список файлов, содержащихся в каталоге, который выуказали в командной строке. В дополнение к функциям для работы скаталогами, которые были рассмотрены выше, Perl предлагает ещенабор фикций, которые позволяют позиционировать текущий указатель в списке каталога:

   $result = rewinddir(DirHandle);
   $result = telldir(DirHandle);
   $result = seekdir(DirHandle, Position);

Форматированный вывод


В этой главе вы познакомились с несколькими способами форматирования выходных данных скрипта с помощью функции print. Аналогично языку С, Perl также поддерживает функции printf и sprintf.В дополнение Perl также поддерживает генерацию отчетов в форместолбцов, используя шаблоны форм.

Использование функции PRINT


В этой главе скрипты широко использовали функцию print. Кроме того, Perl обеспечивает специальные переменные, которые влияютна работу функции print. В таблице 12.5 кратко характеризуютсяэти специальные переменные.

Табл. 12.5. Специальные переменные, которые управляют функциейпечати
Переменная Назначение
$, Разделитель для элементов печати
$" Разделитель элементов списка при интерполяции строки
$\ Разделитель для выходных записей
$# Форматирование числового выхода (по умолчанию '%.20g')

Для использования этих специальных переменных достаточнопросто присвоить им значения, которые вы хотите. Например, в следующем фрагменте программы используется переменная $ для того,чтобы задать сепаратор между элементами печати:

   $, = '*';
   @list = 1..10;
   print @list;      # Выведет 1*2*3*4*5*6*7*8*9*10

Оказывается, что переменная $ на самом деле воздействует навсе строки, а не только на те, которые выводятся на печать. Однако чаще всего вы будете использовать ее для того, чтобы изменитьзначение, выводимое функцией print.

Форматированный вывод данных функцией PRINTF


Perl имеет функции printf и sprintf, которые очень похожи насоответствующие функции библиотеки времени выполнения языка С.Они имеют следующий формат:
   $result = printf([FileHandle] Format, List);
   $result = sprintf(Format, List);

По умолчанию функция printf посылает форматированный выходна стандартный выход STDIO, а функция sprintf возвращает форматированную строку. В обоих случаях формат строк почти аналогиченфункциям языка С, исключая только отсутствие поддержки функциямиязыка Perl спецификатора длины (*). Следующий фрагмент программыиллюстрирует использование функций printf и sprintf.

   $precision = 2;
   $pi = 3.1415;
   printf("%.2f\n", $pi);            # выведет 3.14
   printf("%.${precision}f", $pi); # выведет 3.14

Вызов внешних программ из скрипта на языке PERL


Будучи в известном смысле заменой скриптов shell, Perl обеспечивает поддержку системного взаимодействия, включая вызов внешних программ. В следующих разделах рассматривается несколько способов вызова внешних программ из скриптов Perl. Имейте, однако, ввиду, что позволяя скриптам выполнять системные команды, вы темсамым открываете бреши в системе безопасности вашего узла. Придерживайтесь общего правила не выполнять внешних команд из скрипта на языке Perl. Тем не менее, если вы вынуждены выполнять внешние команды из скрипта, то можете использовать для этих целейвстроенные функции system, exec или fork.

Регулярные выражения


На протяжении этой главы вы познакомились с примерами функций для обработки строк. Многие из них основаны на концепции регулярных выражений. Как вы видите из следующих разделов, скриптыязыка Perl широко используют регулярные выражения для обработкитекста. Если регулярные выражения внове для вас, то не беспокойтесь. Спустя короткое время после того, как вы познакомитесь снесколькими разделами этой главы, регулярные выражения станут длявас просты и понятны.

Обзор регулярных выражений


Регулярные выражения являются причудливым термином, возникшим в компьютерной науке и служащим для обозначения образца, состоящего из символов. Скрипты на языке Perl используют символьныеобразцы просто для того, чтобы провести анализ входных данных,расщепляя их на части. Часто скрипт может проанализировать входные данные, основываясь на пробелах, запятых, символах табуляциии других разделителях. Но когда входные данные имеют произвольный формат то лучше всего с такой задачей справляются регулярные выражения.

Синтаксис регулярных выражений


Для сокращения размеров регулярных выражений, Perl использует специальные символы. Таблица 12.6 содержит список некоторых из символов, используемых скриптами языка Perl в регулярных выражениях.

Табл. 12.6. Символы, используемые в регумрных выражениях
Символ Описание
. Соответствует любому символу (за исключением символа новой строки)
(..) Группирует последовательность элементов
+ Удовлетворяет предыдущему образцу один или большее количество раз
? Удовлетворяет образцу нуль или один раз
* Соответствует образцу один или нуль раз
[...] Соответствует символу из заданного множества
[^...] Соответствует символу из множества, полученного отрицанием
(...|...|...) Соответствует одной из альтернатив
^ Соответствует началу строки
$ Соответствует образцу в конце строки
{n,m} Соответствует образцу от n до m раз
{n} Соответствует образцу точно n раз
{n,} Соответствует образцу минимум n раз
\n\t etc. Соответствует знаку новой линии, символу табуляции и т. д.
\b Соответствует на границе слова
\B Соответствует внутри границ слова
\d Соответствует цифре
\D Соответствует не цифре
\s Соответствует пробелу
\S Соответствует не пробелу
\w Соответствует букве или цифре
\W Соответствует символу, не являющемуся ни буквой, ни цифрой

Perl помещает регулярные выражения (образцы, шаблоны) в слэши, т. е. в наклонные черточки, например, в виде /pattern/. Следующий фрагмент программы иллюстрирует регулярные выражения языка Perl:

   # the following regular expressions are true if:
   /ig/          #    string contains 'ig'
   /(b|d|f)ig/      # string    contains 'big', 'dig' or 'fig'
   /[0-9]+/        #    string contains a number
   /[A-Za-z][A-Za-a0-9_]*/ # string contains an identifier

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

Использование регулярных выражений для поиска по ключевым словам


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

       if ($str =~ /pattern/)

В данном случае регулярные выражения принимают значение <истинно>, если образец найден в строке ($str). Если строка по содержит образца, то выражение возвращает значение <ложно>. Например, следующее выражение проверяет, содержит ли строка текст WebProgramming:

   if ($str =~ /Web Programming/)

Для того, чтобы проверить полное совпадение, выражение должно привязать сравнение к началу и концу строки. Например, следующее выражение имеет значением величину <истинно>, если итолько если переменная $str принимает одно из трех значений:<banana>, <bananana>) <banananana>:

       ($str =~ /^ba(na) {2,4}$/)

Аналогичным образом, следующее выражение истинно тогда итолько тогда, когда переменная $str содержит слово <the> и не является частью другого слова, такого как <their>.

   ($str =~ /\bthe\b/)

Использование регулярных выражений для анализа входных данных


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

   $str = " January 1, 1997, ";
   ($m, $d, $y) = $str =~ /\s*(\S*)\s + (\d+)\D + (\d{4})/;

В этом случае можно прочитать регулярные выражения следующим образом:

   ? Пропустить вначале любой специальный символ;
   ? записать все символы, не являющиеся специальными, в переменную $m 
   ? (переменная    для обозначения месяцев);
   ? пропустить специальный символ;
   ? поместить все цифры в переменную $d (переменная для записи дней);
   ? пропустить все знаки, не являющиеся цифрами;
   ? записать четыре цифры в переменную $у (переменная для обозначения лет).

Perl поддерживает также другую форму сравнения с образцом,использующую оператор (=~), который добавляет отрицание результата: (!~). Этот оператор эквивалентен выражению !($str=~/pattern/).

регулярные выражения для поиска и замены строк


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

       $str =~ s/pattern/replacement/;

Например, следующая инструкция заменит слово <colour> на<color>:

   $str =~ s/\bcolour\b/color/;

Небольшая модификация позволяет заменить все слова <colour>на <color>:

 $str =~ s/\bcolour\b/color/g;

В данном случае g в конце выражения указывает языку Perl нанеобходимость глобальной подстановки.

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

   $str =~ tr/SearchList/ReplacementList/;

Например, замена всех символов нижнего регистра теми же символами верхнею регистра может быть осуществлена таким образом:

   $str =~ tr/a-z/A-Z/;  # меняет регистр, с нижнего на верхний

Проанализируйте сами следующий пример:

   $letters = "abcde";
   print "$letters\n"              # Выведет abcde
   $letters =~ tr/a-z/A-Z/;
   print "$letters\n"              # Выведет ABCDE

РЕЗЮМЕ


В этой главе рассмотрено введение в программирование на языке Perl. Используя рассмотренные здесь концепции, можно писатьсложные скрипты CGI на языке Perl. Следующая глава окажет вам помощь в получении навыков в создании CGI-скриптов на языке Perl,которые можно запустить на собственном сервере. Прежде чем следовать далее, удостоверьтесь, что вы понимаете следующие ключевыеконцепции:

? Perl представляет собой интерпретируемый язык программирования,который используется программистами для написания скриптов дляWeb и Internet.

? Конструкции языка Perl во многих отношениях напоминают аналогичные конструкции языка С, однако Perl предлагает много дополнительных возможностей, в особенности для обработки строк и файлов,которые трудно отыскать в языке С.

? Perl является основным языком для написания CGI-программ дляWeb и Internet, в первую очередь благодаря своей гибкости, компактному стилю и обеспечению высокой безопасности.

Важнейшие WEB-узлы с информацией о PERL


Следующие узлы Web помогут отыскать информацию об интересующих вас деталях относительно языка Pcrl, скриптов на нем, а также специальной информации о ресурсах языка Perl 5 и его библиотеках. Используйте эти Web-узлы в качестве отправной точки вашегопоиска.

http://www.shareware.com/top/Source-Code-table.html - SHAREWARE.COM - самые популярные файлы с кодами программ.
http://www.inxpress.net:80/~moewes/computer/perl95.html - Perl для Windows 95.
http://www.mit.edu:8001/perl/perlapi.html - PERLAPI
http://www.genome.wi.mit.edu:80/ftp/pub/software/WWW/cgi_docs.html CGI.pm - Библиотека Perl5.CGI
http://www.metronet.com/0/perlinfo/perl5/manual/perl.html - PERL
http://www.teleport.com/~rootbeer/perl.html - Ссылки для изучающих Perl

Создание скриптов CGI с помощью PERL


В главе 12 вы познакомились с программированием на языкеPerl. В это главе вы научитесь использовать Perl для созданияскриптов CGI. Коротко говоря, вы получите возможность сочетатьваши знания по языку Perl и CGI, полученные в предыдущих главах.Кроме того, вы узнаете несколько новых приёмов программированияна языке Perl. Как вы уже знаете, можно создать скрипты CGI, используяпрактически любой язык программирования. Чтобы быть грамотнымWeb-программистом, вы должны не только знать, как писать программы для WEB, но также необходимо иметь представление о том, какиесредства использовать для решения специфических задач. За счётправильного выбора языка программирования и программных средств всоответствии с вашей задачей, вы можете значительно повысить эффективность работы и сэкономив много сил и времени. Когда вы используете язык Perl для создания скриптов, можно создать устойчивые профессиональные скрипты за относительно короткий промежутоквремени. Остаток этой главы посвящен изучению программированияCGI-скриптов на языке Perl. К моменту окончания изучения этойглавы вы поймете следующие концепции:

? Perl представляет собой эффективное средство для создания надежных скриптов без написания кодов большого объёма, что выгодноотличает его от других языков программирования, таких как C и С++.

? Версия 5 языка Perl добавляет много новых возможностей, такихкак поддержка объектно-ориентированных скриптов и усовершенствование техники определения области видимости переменных.

Почему разработчики используют Perl для создания CGI- скриптов?

Предыдущие две главы должны были составить у вас представление о том, что такое CGI и почему мощные возможности языка Perlпо обработке текстов делают его хорошо приспособленным для разработки CGI-скриптов. Другие причины и пользования разработчикамиязыка Perl для написания CGI-скриптов заключаются в том, что Perlобеспечивает широкую поддержку взаимодействия с базами данных,обладает переносимостью и обеспечивает безопасность при работе всетях. Как уже говорилось, Perl представляет собой один из наиболее мощных языке программирования для обработки текстов. СкриптыCGI обычно имеют дело с интенсивной обработкой текста: анализомданных, обеспечением доступа к база данных, генерацией HTML-страниц и т. д. Типичный CGI-скрипт, написанный на языке Perl, по своемуразмеру представляет собой фрагмент программы аналогичного назначения, написанной на C++. Как вы увидите дальше в этой главе,Perl обеспечивает поддержку взаимодействия с базами данных. Посуществу, Perl имеет встроенный менеджер баз данных Perl был перенесен почти что на все популярные вычислительные платформы такие как Windows, UNIX, MS, DOS. To обстоятельство, что Perl является 6ecплатным, также увеличивает его привлекательность. Поскольку Perl не использует указателей, то он является более безопасным и надежным языком, чем С и C++. За счет исключения использования указателей предовращается нарушение доступа к памятии связанные с этим ошибки. Кроме того используя регулярные выражения языка Perl, легко проверить целостность входных данных иотфильтровать всякие escape-последовательности, которые МОГУТ угрожать безопасности вашей системы. Наконец, для повышения безопасности имеется специальная версия Perl, называемая taintperl,предотвращающая использование каких-либо входных данных в качестве системных команд. Дополнительную и информацию о taintperlможно найти на Web-узлах, указанных в конце этой главы.

Вызов CGI-скрипта


На UNIX-системах программисты могут исполнять скрипты, написанные на языке Perl, как выполнимые файлы. Иными словами, дляних нет необходимости делать что-то специальное для вызова скрипта. На системах, основанных на DOS или Windows, некоторые серверы не исполняют скрипты Perl автоматически. В этом случае вампридется писать пакетный файл, который вызывает команды Perl длязапуска скрипта. Для некоторых систем придется подробнее познакомиться (. документацией по вашему НТTР-серверу относительно запуска скриптов Perl. Большинство серверов HTTP предполагает, чтоскрипты CGI находятся в каталоге под названием cgi-bin. В этомслучае можно вызвать скрипт с помощью URL, подобно следующему:

       http://your-domain/cgi-bin/your-script

Примечание: В URL задан каталог cgi-bin, но в действительностискрипт может находиться где угодно в системе. Вы должны определить его расположение при установке сервера HTTP.

Вызов СGI-скрипта в системе UNIX


Если вы поместили ваш скрипт в каталог cgi-bin и сделали его выполнимым, то пользователь может вызвать скрипт, непосредственно используя URL. Однако необходимо выполнить несколько шагов. Впервую очередь, в начало скрипта необходимо поместить строку, которая идентифицирует файл как программу на языке Perl:

       #!/usr/bin/perl

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

Далее необходимо сделать скрипт выполнимым, используя командуchmod:

   chmod +x your-srcipt

Вызов скрипта на языке PERL из DOS и WINDOWS


В DOS или Windows скрипты Perl сами по себе не являются выполнимыми самостоятельными программами. Вместо этого необходимозапустить исполнимую программу PERL.EXE, включая имя скрипта наязыке Perl в командной строке. Для упрощения этого процесса можно создать ВАТ-файл для каждого вашего скрипта, который запускает PERL. ЕХЕ с соответствующим файлом, содержащим скрипт. Например, предположим, что ваш ВАТ-файл HELLO.ВАТ содержит следующие команды:

       @echo off
       perl Hello.pl %1 %2 %3 %4 %5    %6 %7 %8 %9

Также предположим, что скрипт Perl Hello.PL содержит следующие инструкции:

   print "Hello, args are '@ARGV'\n";

Как можно видеть, ВАТ-файл просто запускает программуPERL.EXE с указанием скрипта Hello.PL в качестве входной командной строки. Если вы запустите скрипт на языке Perl из Web-сервера, то обнаружите, что большинство HTTP-серверов распознаютскрипты на языке Perl (например, как это делает FolkWeb- сервер),так что нет необходимости в использовании ВАТ-файла. Иными словами, если вы используете HTTP-сервер наподобие FolkWeb, вам нетнадобности делать что-то специальное для вызова CGI-скрипта наязыке Perl. В противном случае может потребоваться создатьВАТ-файл. Если ваша программа-сервер нуждается в ВАТ-файле для выполнения скрипта на языке Perl, вы должны поместить ВАТ-файл (такойкак HELLO.ВАТ) в каталог cgi-bin и туда же - скрипт Perl(Hello.PL).

Создание текста и HTML-документа с использованием языка PERL


Создание текстовых документов с использованием языка Perlпредставляет собой тривиальную задачу. Вам только необходимоудостовериться, что вы поместили правильный НТМL заголовок в начале текстового документа. Например, следующий скрипт создаетпростой текстовый документ, содержащий сообщение Hello, world:

   print "Content-type: text/plain\n\n";
   print "Hello, world\n";

Создание текстовых документов HTML также очень легко. Например, в следующем фрагменте текста создается простой документ HTML:

   print <<HTML;
   Content-type: text/html
 <HTML>
   <HEAD><TITLE>Test Using HTML</TITLE></HEAD>
   <BODY>
   <H1><CENTER>
   Hello, world
   </CENTER></H1>
   </BODY></HTML>
   HTML

Эти примеры больше походят на исходные коды HTML, чем напрограмму на языке Perl. Действительно, если вы удалите несколько строк, вы будете иметь HTML-файл. Эта иллюстративная программа использует свойства языка Perl, которые не были рассмотрены в предыдущей главе, но они достаточно просты для понимания. Строка <<HTML и последняя строка с символами HTML представляют собой конструкцию, называемую <здесь-документ> (heredocument), которая перешла сюда из терминологии программированияshell для UNIX. <Здесьдокумент> представляет собой просто несколько строк литералов. Perl обрабатывает <здесь-документ> какстроку в двойных кавычках. Поскольку <здесь-документ> делает исходный код на языке Perl легким для чтения, то использование такой конструкции является идеальным для создания HTML-документов.Используя конструкцию <здесь-документ>, скрипт на языке Perl может не иметь символов цитирования и символов новой строки, и недолжен содержать функций printf. Конструкция <здесь-документ> широко используется в рассматриваемых далее в этой главе примерах.

Добавление в документ динамических свойств


Если бы возможности CGI-скриптов ограничивались созданием статических форм, то это было бы грустно. Настоящая сила CGI состоит в придании Webстраницам динамики. В главе 11 вы рассматривали программу на языке C++, которая создает скрипт, выводящий наэкран значения переменных окружения. Следующий скрипт на языкеPerl решает идентичную задачу. Тем не менее, вы убедитесь, насколько проще выглядит программа на языке Perl, чем аналогичнаяС++ версия, показанная в главе 11:

   print <<HTML;
   Content-type: text/html
   <HTML>
   <HEAD><TITLE>Echo Environment Variables </TITLE></HEAD>
   <BODY>
   <H3><CENTER>
   Environment Variables:<HR>
   </CENTER></H3>
   for $env (sort keys %ENV)
   {
   print "<LI>$env is $ENV{$env}<BR>";
           }
   print "</BODY></HTML>\n"

Этот пример создает статический заголовок, и затем выводит значения переменных окружения скрипта, используя форматированныйHTML-документ. Скрипт показывает, как использовать конструкцию<здесь-документ> совместно с традиционной функцией print.

Доступ к строке запросов


В главе 11 вы видели, что простым способом передачи данныхCGI в скрипт является использование строки запросов. Броузер передает данные HTTP-серверу как часть URL. В свою очередь серверрассматривает все, что следует за знаком вопроса (?) в URL, какстроку запроса. CGI-скрипт может получить доступ к строке запросов двумяспособами. Либо сервер передает строку запросов скрипту, используя аргументы командной строки, либо сервер присваивает значение строки запросов переменной окружения QUERY_STRING. Например, можно возвратиться к рассмотренному выше скрипту, которыйвыводит на экран значения переменных окружения, и вызвать скрипт,используя строку запросов.


Декодирование форм HTML с использованием метода GET


Как вы увидели, использование подсказки ISINDEX для создания одиночного запроса достаточно просто. Но для получения отпользователя больше чем одного значения необходимо использоватьформы. Следующий скрипт на языке Perl генерирует форму. Используяметод GET, скрипт дает команду броузеру послать значения запросакак часть URL, так же как при использовании ISINDEX. Разница между использованием GET и ISINDEX состоит в том, что при использовании метода GET броузер может соединить несколько величин полейв одну строку запросов, разделяя поля с помощью амперсанда (&).Для того чтобы скрипт мог определять значения полей, броузервключает имена полей в строку запроса. Например, если база данных содержит три поля (имя, возраст и день рождения) с такимизначениями (Bob, 27, 11-1-68), то строка запросов будет содержать значения полей в следующем формате:<name=Bob&age==27&birthday=l 1-1-68>. В следующем примере скриптдекодирует поля и выводит на экран их значения с помощью создания HTML-формы:

       ($cgi_bin, $cgi_script) = ($0 =~ m:(.*)[/\\](.*):);
       $query = $ENV{QUERY_STRING};
       if ($query eq '')
       {
           # сгенерируем форму
           print <<FORM;
   Content-type: text/html
   <HTML>
   <HEAD><TITLE>Sample GET Form </TITLE></HEAD>
   <BODY>
   What is your query? <P>
   <FORM METHOD="GET" ACTION="$cgi_script">
   A checkBox. <BR>
   <INPUT TYPE="checkbox" NAME="chek" VALUE="on"><P>
   A radio button set. <BR>
   <INPUT TYPE="radio" NAME="button" VALUE="1">    1<BR>
   <INPUT TYPE="radio" NAME="button" VALUE="2">    2<BR>
   <INPUT TYPE="radio" NAME="button" VALUE="3">    3<P>
   A data entry field<BR>
   <INPUT NAME="field"><P>
   Send the data.<BR>
   <INPUT TYPE="submit">
   </FORM>
   </HTML>
   FORM
       }
   else {
       # распечатаем результаты
       print "Content-type: text/html\n\n";
   print "<HTML>\n";
   print "<HEAD><TITLE>GET Form Result</TITLE></HEAD>\n"
   print "<BODY>\n";
   print "Your query values:<P>\n";
   @fields = split('&', $query);
   forech (@field) {
       Switch: {
           /^check=(.*)/ &&    do {
                  $check = $1;
                  last Switch;
           };
           /^button=(.*)/ &&    do {
                  $button = $1;
                  last Switch;
           };
           /^field=(.*)/ &&    do {
                  $field = $decode(1);
                  last Switch;
           };
       }
   }
       print "Check Box: $check<BR>\n";
       print "Radio Button: $button<BR>\n";
       print "Data Field:", &html($field),    "<BR>\n";
       print "<HTML>\n";
   }
       sub decode{
           local ($value) = @_;
           $value =~ s/\+/    /g;
           $value =~ s/%([0-9A-H]{2})/pack('C',hex($1))/eg;
           return $value;
           }
       sub html {
           local ($value) = @_;
           $value =~ s/</&lt;/g;
           $value =~ s/>/&gt;/g;
           return $value'
           }

Обратите внимание на первую строку скрипта:

   ($cgi_bin, $cgi_script) = ($0 =~ m:(.*)[/\\](.*):);

Это выражение выглядит похожим на аналогичное выражение впредыдущем примере. Однако в данном случае скрипт разделяет путьна каталог и имя файла. В этом примере один и тот же скрипт создает форму и обрабатывает ее вывод, что достаточно нетрудно выполнить. Такой способ рекомендуется для обработки форм, потомучто концентрирует всю обработку в одном месте. Скрипт определяет, создавать ли форму или обработать запрос,в зависимости оттого, поступил ли запрос от пользователя. Для обработки строки запросов скрипт разделяет запрос на поля, используя функцию split. Далее скрипт сравнивает поля запроса сожидаемыми именами полей. Рассмотрим следующий пример:

 forech (@field) {
   Switch: {
       /^check=(.*)/ && do {
           $check = $1;
           last Switch;
       };

Обычная форма цикла foreach включает переменную {$VAR). Еслицикл foreach опускает эту переменную, то Perl использует переменную по умолчанию $_. Аналогично, оператор регулярного выраженияобычно выглядит следующим образом $VAR=~/PATTERN/. Если переменная в выражении опущена, Perl использует $_ как переменную поумолчанию, в результате чего цикл и регулярное выражение соответствуют друг другу. Однако если слишком полагаться на переменныепо умолчанию, то код на языке Perl может получиться неясным. Вданном же случае использование переменных, определенных по умолчанию, делает код более коротким и лучше читаемым. Далее обратите внимание на регулярное выражение, имеющееформу /^field=(. *)/. Данное выражение указывает на необходимость начать поиск от начала строки, что предотвращает совпадения в середине имени другого поля. Иными словами, имя поля и знакравенства (=) должны соответствовать сами себе. Остающаяся частьрегулярного выражения соответствует значению поля и извлекает егов переменную $1. Поскольку $1 представляет собой временную переменную, то скрипт копирует ее в переменную с именем для каждогополя. Скрипт использует подпрограмму decode для декодированиясимволов из полей, которые были закодированы броузером. Регулярные выражения, используемые подпрограммой декодирования, рассматривались в предыдущем примере. Наконец, скрипт использует подпрограмму html, чтобы закодировать значения данных для вывода их в тексте HTML. Скрипт можетпослать большую часть текста броузеру в виде HTML-документа безвыполнения какой-либо обработки. Однако поскольку HTML использует угловые скобки (<>) для кодирования НТМL-входов, скриптдолжен закодировать эти скобки, используя последовательности HTML&lt; и &gt;.

Декодирование HTML-форм с помощью метода POST


Следующий скрипт очень напоминает только что обсуждавшийся,за исключением того, что данный скрипт использует метод POST дляпосылки данных формы скрипу CGI. Метод POST дает директиву броузеру послать данные формы, используя стандартный вход скрипта, ане строку запросов. Полезность метода POST заключается в том, чтоон может обрабатывать большие объемы данных, тогда как метод GETограничен пространством переменной сервера, а также длиной URLброузера. Для чтения данных со стандартного ввода скрипт может вызвать функцию sys-read с нужным числом байт. Размер строки запроса в байтах содержится в переменной окружения CONTENT_LENGTH.После того как скрипт прочел строку запросов, дальнейшая обработка данных оказывается очень похожей на рассмотренную в предыдущем примере. Для того чтобы сделать, этот скрипт более коротким,обработка строки запросов осуществляется с помощью несколько более сложного подхода:

   ($cgi_bin, $cgi_script) = ($0 =~ m:(.*)[/\\](.*):);
   $content_length = $ENV(CONTENT_LENGTH);
   if (!definet($query) || $query eq '') {
       # сгенерируем форму
           print <<FORM;
   Content-type: text/html
   <HTML>
   <HEAD><TITLE>Sample POST Form </TITLE></HEAD>
   <BODY>
   What is your query? <P>
   <FORM METHOD="POST" ACTION="$cgi_script">
   A checkBox. <BR>
   <INPUT TYPE="checkbox" NAME="chek" VALUE="on"><P>
   A radio button set. <BR>
   <INPUT TYPE="radio" NAME="button" VALUE="1">    1<BR>
   <INPUT TYPE="radio" NAME="button" VALUE="2">    2<BR>
   <INPUT TYPE="radio" NAME="button" VALUE="3">    3<P>
   A data entry field<BR>
   <INPUT NAME="field"><P>
   Send the data.<BR>
   <INPUT TYPE="submit">
   </FORM>
   </HTML>
   FORM
       }
   else {
       # распечатаем результаты
       print "Content-type: text/html\n\n";
   print "<HTML>\n";
   print "<HEAD><TITLE>POST Form Result</TITLE></HEAD>\n"
   print "<BODY>\n";
   print "Your query values:<P>\n";
   @fields = split('&', $query);
   forech (@field) {
           /([^=](.*)/    && do {
           local ($filed, $value)    = ($1, $2);
           $query{$field}    = &decode($value);
       }
   }
       print "Check Box: $query{check}<BR>\n";
       print "Radio Button: $query{button}<BR>\n";
       print "Data Field:", &html($query{field}),    "<BR>\n";
       print "<HTML>\n";
   }
       sub decode{
           local ($value) = @_;
           $value =~ s/\+/    /g;
           $value =~ s/%([0-9A-H]{2})/pack('C',hex($1))/eg;
           return $value;
           }
       sub html {
           local ($value) = @_;
           $value =~ s/</&lt;/g;
           $value =~ s/>/&gt;/g;
           return $value'
           }

Этот скрипт использует одно регулярное выражение для анализа всех значений полей в строке запроса:

         /([^=](.*)/    && do {
       local ($filed, $value) = ($1, $2);
       $query{$field} = &decode($value);
   }

Вместо того чтобы присваивать значения каждого запроса отдельной переменной. данная программа хранит все запросы в ассоциативном массиве. В свою очередь скрипт может индексировать массив, используя нужные имена полей. Обратите внимание на сочетание [^=] в регулярном выражении. В данном контексте знак (^) неявляется якорем, указывающим на начало строки, как это было впредыдущем примере. В данном случае этот знак служит отрицаниемДля знака [=]. В таком качестве регулярное выражение может бытьпрочитано так: <соответствует одному или более символам, не включая знак равенства затем соответствует знаку равенства и затемсоответствует всем остающимся, символам>.

Использование библиотеки CGI-LIB языка PERL для декодирования форм


Общедоступная библиотека Perl cgi-lib.pl упрощает обработку CGI-форм. Она содержит несколько полезных подпрограмм, однаконаибольший интерес представляет подпрограмма ReadParse, котораячитает и анализирует данные формы. Одним из больших достоинствcgi-lib является то, что она прозрачно обрабатывает любой типформ (ISINDEX, GET, POST) и даже формы, состоящие из многих частей для ввода больших объемов данных. Некоторые подпрограммы, такие как PrintHeader, HtmlTop,HtmlBot создают стандартные HTML-последовательности, но они слишком просты и не так полезны, как хотелось бы. Для использованияcgi-lib вы включаете исходные коды с помощью директивы require.Вы можете инсталлировать cgi-lib.pl туда же, где установленастандартная библиотека Perl (обычно C:\PERL\LIB для DOS- иWindowsсистем) или вы можете ссылаться на нее, используя указание полного пути. Для получения дополнительной информации или длязагрузки библиотеки cgi-lib.pl посетите Web-узел http://www.bio.cam.ac.uk/cgi-lib

Резюме


В этой главе вы познакомились с тем, как использовать Perlдля написания достаточно сложных скриптов CGI. Используя ту технику, с которой вы познакомились можете, услуги программиста профессионального уровня вашим клиентам, которые желали бы, чтобы ихбизнес был представлен на Web. В главе 14 вы познакомитесь с языком Java. Как вы увидите, язык Java хорошо приспособлен для создания узлов Web, содержащих анимацию и мультимедиа. Дополнительно глава 14 представляет другой язык для написания скриптов JavaScript. Однако перед тем как переходить к главе 14, проверьте, понимаете ли вы следующие ключевые концепции:? Perl представляет собой разносторонний и гибкий язык программирования, с помощью которого можно разрабатывать скрипты CGI дляWeb, а также традиционные программы для каждодневного использования.

  • Perl хорошо приспособлен для обработки текстов, организациидоступа к базам данных, он является переносимым языком и обеспечивает безопасность при работе в сетях. Все эти его характеристики являются важными для Webпрограммирования.
  • Для обработки текстов скрипты языка Perl широко используют регулярные выражения.
  • Большинство скриптов на Web в настоящее время написаны на языке Perl. Однако такие языки, как JavaScript и VBScript, могут посягнуть на монополию языка Perl.

Важнейшие WEB-узлы с информацией по созданию СGI-скриптов с использованием PERL


Следующие Web-узлы помогут вам узнать больше деталей относительно использования языка Perl для создания CGI-скриптов, а также об объектноориентированном программировании. Используйте этиузлы в качестве отправной точки вашего исследования Web.

http://www.globalserve.net/~brent/tech/perl/index.html - Watermarks: исходный код Perl
http://iamwww.unibe.ch/~scg/Src/ - Архив скриптов SCG
http://sunsite.unc.edu/jem/source.html - Исходный код
http://www.metronet.com:70/1/perlinfo/scripts - Скрипты Perl для многих целей
http://worldwidemart.com/script/ - Маттовский архив скриптов
http://www.bio.cam.ac.uk/cgi-lib/ - Home страница CGI-LIB.PL


Реклама на InfoCity

Яндекс цитирования



Финансы: форекс для тебя








1999-2009 © InfoCity.kiev.ua