Программирование CGI-скриптов на Перле

Владивостокский государственный университет экономики и сервиса

Максим Мамаев


Предварительные требования: знание языка С, работа в Unix, понятие о регулярных выражениях. И, естественно, темы 5 и 6 курса "Технологии Интернет".

Литература и ссылки





Установка Перла и библиотек (Unix)

Архивы самого языка Перл и его библиотек распространяются свободно и доступны через сайты CPAN. Библиотеки Перла называются модулями (стандартное расширение .pm), а сами программы - скриптами. И модули, и скрипты являются текстовыми файлами.

Для установки языка Перл необходимо иметь в системе компилятор С (желательно, gcc). Распаковать архив с языком (на текущий момент 27.11.99 это perl5.005_03.tar.gz). В каталоге, куда распаковался архив, выполнить следующие команды: ./configure # configure задаст много вопросов, на все можно ответить нажатием Enter (т.е. принять значение по умолчанию) make # перейти в режим суперпользователя make install

По умолчанию perl установится в /usr/local (исполнимые файлы - в /usr/local/bin/, библиотеки - в /usr/local/lib/perl5/, документы справочника man - в /usr/local/man (по самому языку) и в /usr/local/lib/perl5/5.00503/man (по библиотекам). Следует добавить соответстующие пути в переменные окружения PATH и MANPATH (в файле .profile).

Для запуска программ, написанных на Перле надо подать команду perl имя_файла_с_программой или просто ввести имя файла с программой, если в первая строка этого файла выглядит: #!/usr/local/bin/perl

Перл поставляется с несколькими стандартными модулями. Для работы с CGI требуется взять из CPAN и установить следующие библиотеки (в указанном порядке):

  1. Digest-MD5
  2. MIME-Base64
  3. URI
  4. HTML-Parser
  5. libnet
  6. libwww-perl
  7. CGI

Установка каждой библиотеки производится командой perl Makefile.PL && make && make test && make install поданной в каталоге, куда распаковаля архив библиотеки. Для выполнения последней части команды (make install) требуются привилегии суперпользователя.

Библиотеки устанавливаюися в дерево /usr/local/lib/perl5/. Документы man по установленным библиотекам находятся в /usr/local/lib/perl5/5.00503/man.

Минимальное введение в Перл

В этом разделе дана минимальная необходимая информация по тем элементам Перла, которые чаще всего используются при написании скриптов. Перл здесь рассматривается как С-подобный язык, поэтому акцентируются отличия от С. Этот раздел ни в коей мере не претендует на описание языка Перл (многие моменты сознательно опущены); для этой цели обратитесь к Camel Book, Llama Book или книге Маслова.

Комментарий "отсюда и до конца строки" - символ "#".

Типы переменных

Переменные бывают трех типов: скаляры, списки и хэши. Описывать переменные не нужно, если только вы не используете директиву "use strict"; иначе каждая переменная должна быть описана с помощью "my имя_переменной".

Скаляры

Скаляр содержит одно значение; это может быть строка или число, Перл сам определяет тип значения по контексту проводимых со скаляром операций. Например, при попытке конкатенировать два скаляра операцией "." они будут рассмотрены как строки, а при попытке сложить их значения операцией "+" - как числа. При проведении числовых операций над строками, значение которых не может быть интерпретировано как число, числовое значение такого скаляра считается нулевым (см. также ниже п. Операторы, выражения и операции).

Повтор специально для программистов на С: строковые значения не оканчиваются на символ "\0". Строковых значений как таковых вообще не существует, строка - это один из двух способов интерепретации значения скаляра, который сам по себе ни на что особенное не заканчивается.

Имена всех скалярных переменных обязаны начинаться на $ ($x, $my_variable_1).

  • Имеется специальное скалярное значение undef - "неопределенность". Такое значение имеют, например, переменные, которым не было присвоено никакого значения. В логических и арифметических операциях undef считается нулем, в строковых операциях - пустой строкой. Функция defined(выражение) возвращает истину, если выражение не равно undef (хотя может быть равно нулю). my $x; # $x создается, равно undef $x; # ложно defined($x); # ложно $x=0; $x; # ложно defined($x); # истинно $x=5; $x; # истинно defined($x); # истинно $x=undef; # опять undef!

    Списки и массивы

    Списком (list) называется упорядоченная последовательность скалярных значений; порядковые номера (индексы) начинаются с нуля. Отдельно стоящие списки заключаются в скобки: ($x, "abc", 15) Обращение к элементу списка осуществляется путем указания индекса этого элемента в квадратных скобках: $y=($x, "abc", 15)[1]; # $y="abc"

    Переменная, значением которой является список, называется массивом (array). Имена всех массивов обязаны начинаться с @ (@array). При обращении к элементу массива знак @ заменяется на $: $array[0] $array[$x] $array[-2] # второй элемент с конца (смысл: элемент массива - это скаляр, следовательно он начинается с $). Примеры формирования массивов: @array=($x, "abc", 15); @array=($x, $y, @another_array); @array=(); #пустой список Количество элементов в массиве: scalar @array (см. также п. "Контексты" ниже); индекс последнего элемента: $last_index = $#array.

    Извлечение части массива: ($a, $b, $c) = @array[3,4,5]; @sublist=@array[3,4,5]; Соответственно, наоборот: @array[3,4,5]=($a,$b,"xyz"); производит присвоение значений части массива @array (если элементы @array[0-2] ранее отсутствовали, они создаются со значениями undef).

    Двух- и более мерные массивы в явном виде не поддерживаются.

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

    @list = reverse @array @list = reverse список
    - возвращает список, состоящий из значений массива @array, взятых в обратном порядке (сам массив @array не изменяется). Аргументом функции reverse может быть не только массив, но любое выражение, имеющее списочное значение.

    push @array, $x push @array, список
    - помещает значение или список значений в конец массива. Список может быть как явным перечислением значений через запятую, так и любым выражением, имеющим списочное значение. Функция push возвращает новую длину массива @array.

    $x = pop @array
    - извлекает из массива последний элемент (элемент из массива удаляется). Если массив не указан - подразумевается список аргументов функции (т.е. массив @_), если вызов произведен внутри какой-либо функции, или аргументы командной строки скрипта (т.е. массив @ARGV), если вызов произведен из основной части скрипта.

    $x = shift @array
    - извлекает из массива первый элемент (элемент из массива удаляется). Если массив не указан - подразумевается список аргументов функции (т.е. массив @_), если вызов произведен внутри какой-либо функции, или аргументы командной строки скрипта (т.е. массив @ARGV), если вызов произведен из основной части скрипта.

    unshift @array, $x unshift @array, список
    - аналогично push, но новые элементы помещаются в начало массива @array.

    @list = splice @array, $from, $length, список @list = splice @array, $from, $length @list = splice @array, $from
    - удаляет из массива @array $length элементов, начиная с индекса $from. Если присутствует список, то вместо удаленных элементов помещаются значения из списка; если их больше, чем удаленных, то массив увеличивается, если меньше - то соответственно уменьшается. Если $length отсутствует, то удаляются все элементы, начиная с индекса $from. Индекс $from может быть отрицательным - тогда счет производится с конца, т.е. splice(@array,-2) удаляет два последних элемента из массива @array, а splice(@array,-2,1) удаляет предпоследний элемент. Функция splice возвращает список удаленных из массива элементов. Функции push, pop, unshift и shift являются частными случаями функции splice.

    Хэши

    Переменная-хэш представляет собой массив, элементы которого индексируются строками (ассоциативный массив). Порядок хранения элементов в хэше не определен. Имена всех переменных-хэшей обязаны начинаться на % (%my_hash). При обращении к элементу списка знак % заменяется на $ и используются фигурные скобки: $hash{"key_A"} $hash{$x} Хэши могут быть сформированы с помощью объединения четного числа скаляров в скобки: %hash=("abc", $x, "def", 15); # $hash{abc}=$x и $hash{def}=15 #запятые для удобо читаемости могут быть заменены на "=>" %hash=("abc" => $x, "def" => 15); %hash=(); #пустой хэш Вообще, любой список (массив) может быть рассмотрен в качестве хэша, т.е. %hash=@array. При этом нечетные элементы списка станут ключами хэша, а четные - соответствующими значениями. Если число элементов в списке нечетное, то последний элемент сконструированного таким образом хэша будет существовать со значением undef ("неопределенность"). Если в списке есть одинаковые элементы на нечетных позициях, то в хэш будет внесено значение, ключом которого является последний из одинаковых нечетных элементов списка. @array=('a',1,'b',2,'c'); # для 'c' нет пары %hash=@array; # получилось: $hash{c}=undef %hash=('a' => 1, 'b' => 2, 'a' => 3); # получилось: $hash{a}=3

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

    Функции для работы с хэшами:

    @array = keys %hash
    - возвращает список ключей хэша (порядок неопределен).

    @array = values %hash
    - возвращает список значений хэша (порядок неопределен, но для одного и того же хэша всегда совпадает с порядком выдачи ключей функцией keys).

    ($key, $value) = each %hash
    - возвращает список из двух скаляров: ключ и значение очередного элемента хэша; используется в циклах для прохода по всем элементам хэша.

    exists $hash{$key}
    - возвращает истинное (ненулевое) значение, если указанный элемент хэша существует (хотя, может быть, и равен нулю или имеет неопределенное значение).

    delete $hash{$key}
    - удаляет указанный элемент хэша.

    %rev_hash = reverse %hash
    - меняет местами ключи и значения элементов хэша; работает корректно в случае, если в хэше %hash не было элементов с одинаковыми значениями.

    Операторы, выражения и операции

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

    Контексты

    Каждое выражение в Перл вычисляется в списочном, либо скалярном контексте. То есть в списочном контексте предполагается, что значение выражения должно быть списком, а в скалярном - скаляром. Контекст определяется, например, типом переменной, стоящей в левой части оператора присвоения. Многие функции определяют контекст, в котором они были вызваны и возвращают разные результаты в зависимости от контекста. Например, функция localtime (текущее местное время) в скалярном контексте возвращает строку вида "Fri Nov 26 20:36:33 1999", а в списочном контексте - список из чисел: секунды, минуты, часы, день месяца, месяц и т.д. Для того чтобы форсировать скалярный контекст, можно использовать оператор scalar. $x = localtime; # скалярный контекст @time = localtime; # списочный контекст ($sec,$min,$hour) = localtime[0,1,2]; # списочный контекст print scalar localtime; # скалярный контекст

    Значением списка в скалярном контексте является длина списка: $x=@array; # в переменную $x помещается длина списка @array Значением скаляра в списочном контексте является список, состоящий из одного этого скаляра.

    Значения выражений и операции

    • Большинство арифметических и логических операций аналогично операциям языка С (в том числе операции типа $x++; ++$x; $x += 5; $x=$y=5). Различия рассмотрены ниже.

    • Результат многих операций может быть рассмотрен как истинное (ненулевое) или ложное (нулевое или неопределенное) значение. Можно использовать операции "И" ("&&" или "and") и "ИЛИ" ("||" или "or") для выстраивания цепочки действий, которые выполняются в зависимости от успеха (истинного значения) или неуспеха предыдущего действия. Это позволяет сократить запись (иначе пришлось бы использовать оператор if). # открыть файл myfile.txt, присвоив ему дескриптор FILE, # или выйти из программы с сообщением об ошибке open (FILE, "myfile.txt") or die ("Cannot open file"); # вывести сообщение в случае существования элемента хэша exists $hash{"mykey"} and print "My key exists!"; # присвоить переменной $x значение 5, если $x имеет неопределеное или нулевое значение $x ||= 5;

    • Имеется ряд операций для работы со скалярами как со строками. Операция "." (точка) вызывает конкатенацию строк: $x = "Now is " . scalar localtime; $x .= " (time is local)."; # то же что $x = $x . " (time is local)."; Сравнения скаляров как строк выполняются следующими операциями:
      $a eq $bИстинно, если $a и $b одинаковы
      $a ne $bИстинно, если $a и $b неодинаковы
      $a lt $bИстинно, если $a раньше по алфавиту, чем $b
      $a gt $bИстинно, если $a позже по алфавиту, чем $b
      $a le $bИстинно, если $a раньше по алфавиту или совпадает с $b
      $a ge $bИстинно, если $a позже по алфавиту или совпадает с $b
      $a cmp $b-1, если $a раньше по алфавиту, чем $b; 0, если $a и $b одинаковы; 1, если $a позже по алфавиту, чем $b

      Внимание, распространенная ошибка! Операции "== != > < >= <=" выполняют сравнение скаляров как чисел. Использование их в "скалярно-строковом" контексте приведет к неверным результатам. Например, "11">"2", но "2"gt"11". Более того, $a="xyz"; $b="qwerty"; $a==$b - истинно, поскольку как числа обе этих переменных равны нулю.

    • Дополнительная операция для сравнения скаляров как чисел: $x<=>$y равно -1, если $x<$y; 0, если $x=$y; 1, если $x>$y.

    • Если в выражении не указано, откуда берутся или куда возвращаются данные, то подразумевается, что речь идет о переменной $_ (в скалярном контексте) или о @_ (в списочном контексте). # читать из файла с дексриптором FILE по одной строке (оператор <FILE>) # и удалять символ перевода строки из конца прочитанной строки (функция chomp) while ($a=<FILE>) { chomp $a; } # то же самое, используется переменная $_ while (<FILE>) { chomp; }

      Операторы

    • Имеются аналогичные языку С операторы if (...) {...}; условие ? выражение_да : выражение_нет ; while(...) {...}; do {...} while (...); for (...;...;...;) {...}; Отличия и дополнения рассмотрены ниже.

    • Фигурные скобки, определяющие блок операторов, выполняемый после оператора ветвления или цикла, должны быть всегда, даже если блок операторов состоит из одного оператора: if ($a<$b) { $a=$b; } while ($a<$b) { some_function($a); } Однако для операторов ветвления в таком случае есть сокращенная "постфиксная" форма записи: $a=$b if ($a<$b);

    • Скобки вокруг аргументов стандартных функций не требуются (если только не возникает неоднозначностей): print "a=",$a; НО: join ':', split ('/', $a); или join ':', split ('/'), $a;

    • Оператор foreach производит цикл по всем элементам списка: foreach $i (@array) { print $i; } # то же самое с использованием переменной $_ foreach (@array) { print; }

    • Оператор unless - это оператор if с отрицанием: # присвоить переменной $x значение 5, если $x имеет неопределеное или нулевое значение unless ($x) { $x=5; } # то же, что и $x ||= 5; Будьте внимательны при программировании сложных условий с помощью unless - помните теорему де Моргана: отрицание произведения есть сумма отрицаний; отрицание суммы есть произведение отрицаний.

    • Оператор until - это оператор while с отрицанием: until ($array[$i++] == $x) {;} соответственно и do {...} until(...).

    • Оператор switch отсутствует. Пользуйтесь конструкцией if () ... elsif () ... elsif () ... else ... или изобретайте что-то свое.

      Управление циклами:

      • досрочный переход на следующую итерацию ближайшего объемлющего цикла - next (аналог оператора continue в С): foreach $i (@array) { next if ($i<0); $sum += $i; }
      • досрочный выход из ближайшего объемлющего цикла - last (аналог оператора break в С): # считывать строки из файла и выводить на печать, пока не встретится пустая строка while ($a=<FILE>) { chomp $a; last unless ($a); print $a, "\n"; }
      • каждый цикл может быть снабжен меткой, на которую могут ссылаться операторы next и last; это позволяет производить выход сразу из нескольких объемлющих циклов: # это не самый лучший алгоритм поиска одинаковых слов в двух списках, # зато здесь используется выход сразу из двух циклов M1: foreach $i (@array1) { foreach $j (@array2) { if ( $i eq $j ) { last M1; } } }

      Кавычки и интерполяция

      Строковые выражения заключаются в одинарные (') или двойные (") кавычки. Везде внутри двойных кавычек производится подстановка переменных - скаляров, элементов списков и элементов хэшей; целые списки подставляются как подстрока в которой все элементы списка следуют друг за другом без разделителя; хэши целиком не подставляются. Для экранирования спецсимволов внутри двойных кавычек используется обратный слэш: \$, \@, \", \\; также распознаются все спецсимволы языка С: \n, \t и т.п. $x="abc"; @array=('c','d','e'); %hash=( a => "A", b=> "B"); print "this is \$x: \"$x\"; \nthis is element 2 of \@array: \"$array[2]\";\n", "and \$hash{a} is \"$hash{a}\"\n"; ВЫВОД: this is $x: "abc"; this is element 2 of @array: "e"; and $hash{a} is "A"

      Строки, употребляемые как ключи хэшей, если это буквальные строки без подстановок ("abc"), в кавычки можно не заключать: $hash{abc}.

      Внутри одинарных кавычек никакие подстановки не производятся, спецсиволы типа "\n" не интепретируются и все символы воспринимаются буквально; исключение: комбинация \' (обратный слэш - одинарная кавычка), которая интепретируется как одинарная кавычка, являющаяся частью строки. Одинарная кавычка внутри двойных кавычек воспринимается буквально.

      Работа с регулярными выражениями

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

      Регулярные выражения (РВ) Перла - надмножество РВ grep/awk, используемых в Unix. В РВ следующие символы имеют специальное значение: \ | ( ) [ { ^ $ * + ? . /

      Символы "]" и "}" имеют специальные значения, только когда встречаются после соответственно "[" и "{". Все прочие символы в РВ воспринимаются буквально. Символ "/" имеет специальное значение не в регулярном выражении, а как признак начала и конца регулярного выражения (см. ниже примеры). Ниже кратко описаны наиболее часто используемые метасимволы РВ и их значения.

      . (точка)
      - любой единичный символ, кроме \n (если только не используется модификатор s - см. ниже).

      *
      - ноль или более появлений РВ, непосредственно предшествующего этому символу.

      +
      - одно или более появлений РВ, непосредственно предшествующего этому символу.

      ?
      - ноль или одно появлений РВ, непосредственно предшествующего этому символу.

      ^
      - начало строки.

      $
      - конец строки.

      [символы] [^символы]
      - один символ из (не)перечисленных внутри скобок. Все метасимволы внутри квадратных скобок теряют свое специальное значение, кроме символа "^", если он находится непосредственно после открывающей скобки (в этом случае он обозначает отрицание набора символов); если символ "^" находится не сразу после открывающей скобки, он воспринимается буквально. Если символ "]" находится непосредственно за открывающей скобкой или непосредственно за комбинацией "[^", он воспринимается буквально, а не как закрывающая скобка; в этом случае должна быть еще одна закрывающая скобка.

      (РВ)
      - группировка регулярного выражения РВ. Используется в том числе и для последующей ссылки на часть строки, которая соответствует РВ.

      |
      - операция "ИЛИ" - требуется срабатывание хотя бы одного из РВ, находящихся слева и справа от символа "|".

      \s
      - любой пробельный символ (то же, что [ \t\n\r\f]).

      \w
      - любой алфавитно-цифровой символ (то же, что [a-ZA-Z_0-9]).

      \d
      - любая цифра (то же, что [0-9]).

      \b
      - граница слова.

      \S, \W, \D, \B
      - отрицание регулярных выражений, соответственно, \s, \w, \d, \w.

      $переменная
      - подстановка значения переменной.

      \
      - экранирует следующий метасимвол так, что он воспринимается буквально.

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

      • i - игнорировать различие прописных и строчных букв (в общем случае - только для латиницы),
      • s - воспринимать скалярное выражение, подлежащее обработке, как состоящее из нескольких строк, разделенных символами \n (т.е. метасимволы ^ и $ будут срабатывать на символах \n, которые возможно встретятся внутри обрабатываемого скалярного выражения),
      • m - воспринимать скалярное выражение, подлежащее обработке, как одну строку, независимо от того, встречаются ли внутри этого выражения символы \n или нет (т.е. метасимволы ^ и $ не будут срабатывать на символах \n, но метасимвол . будет срабатывать на \n).

      Обратите внимание, что метасимволы $, ^, \b не поглощают символы обрабатываемой строки, т.е. например, ^ - это не первый символ строки, а начало строки как таковое; аналогично, \b - это не первый или последний символ слова, а граница между символами типа \W и \w. Иначе говоря, слово cat соответствует РВ /^c/, а слово act ему не соответствует; или в строке "a yellow cat" регулярному выражению /\byellow\b/ соответствует подстрока "yellow", а не " yellow " или "ello".

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

      Поиск РВ в строке: $s =~ /РВ/модификаторы; $s !~ /РВ/модификаторы; Операция возвращает в скалярном контексте "Истинно", если строка $s (не) соответствует РВ, иначе возвращается "Ложно". Если $s не указано, используется $_. if ( $d =~ /vvsu\.ru$/ ) { ... } if ( /^From: /i) { ... }

      Оператор замены

      Замена части строки: $s =~ s/РВ/замена/модификаторы; Операция производит поиск подстроки строки $s, соответствующей РВ, после чего заменяет эту подстроку на замену. Если указан модификатор g, то заменяются все подстроки, соответствующие РВ, иначе заменяется только первая найденная подстрока. Операция возвращает количество произведенных замен. Если $s не указано, используется $_. Подстановку переменных можно использовать и в РВ, и в замене. В части замена можно использовать также спецсимволы $1,$2,..., которые произведут подстановку соответствующей части РВ, взятой в скобки. Примеры: #в строке $x поменять первые два поля местами; #$1 ссылается на первое выражение в скобках в первой части оператора, $2 - на второе $x =~ s/([^ ]*) *([^ ]*)/$2 $1/; #убрать точку с конца строки $_ s/\.$//; #заменить все слова white на black в переменной $_ s/\bwhite\b/black/ig; #заменить в $_ все выражения #include_date на текущую дату #используется модификатор e, говорящий о том, #что вторая часть оператора должна быть воспринята как Перл-код s/#include_date/localtime/eg; #то же самое, но текст "#include_date" хранится в переменной $date_token s/$date_token/localtime/eg;

      Работа с файлами и запуск других программ

      Чтение и запись файлов осуществляется через переменную-дескриптор файла. Имя такой переменной не имеет специального префикса и, как правило, записывается прописными буквами. Дексриптор создается при вызове функции open. Дескрипторы файлов не требуется предварительно объявлять даже при использовании "use strict".

      Открытие файла open (FILE, "filename") or die ("Cannot open filename: $!"); Функция open возвращает "ложно" в случае невозможности открыть файл, в этом случае выполняется функция die, которая выводит свой аргумент на печать и завершает работу скрипта. Переменная S! - стандартная переменная Перла, содержит описание последней возникшей системной ошибки.

      FILE - дескриптор файла, он будет использован ниже в операциях чтения, записи и закрытия файла.

      В приведенном примере файл filename открывается для чтения. Для открытия файла на запись с нуля его имя нужно предварить символом ">" (если файл до этого существовал, его содержимое пропадет); для открытия на добавление в конец - предварить символами ">>": open (FILE, ">filename") or die ("Cannot open filename: $!"); open (FILE, ">>filename") or die ("Cannot open filename: $!"); #открыть для чтения и записи open (FILE, "+>filename") or die ("Cannot open filename: $!"); Для любого скрипта при его запуске по умолчанию открываются дескрипторы STDIN, STDOUT и STDERR.

      Чтение из файла

      Оператор <FILE> производит чтение из файла с дескриптором FILE. В скалярном контексте (например, в условии цикла while) оператор при кадом вызове возвращает очередную строку текста до следующего символа перевода строки включительно. В списочном контексте возвращается список всех текстовых строк от текущей позиции до конца файла. # скалярный контекст while (<FILE>) { chomp; if ($_ eq "this text") { do_someting(); } } # списочный контекст @all_lines=<FILE>;

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

      Еще одна распространенная ошибка! Оператор <> (внутри скобок пусто) считывает не из стандартного ввода, а из файлов, имена которых указанны как аргументы командной строки. При завершении одного файла ввод продолжается с начала следующего файла в том порядке, в каком имена файлов указаны в командной строке. Открывать файлы при использовании оператора <> не требуется.

      Запись в файл

      print FILE "эта строка печатается в FILE\n";

      Закрытие файла

      close FILE; Хотя при выходе из скрипта Перл и закрывает все незакрытые файлы, настоятельно рекомендуется делать это явным вызовом функции close во избежание различных побочных эффектов.

      Вывод в программу

      Для передачи данных в стандартный ввод другой программы нужно создать с помощью open соответствующий дескриптор файла (при этом программа будет запущена) и вывести в него данные. Для создания такого дескриптора вторым аргументом в функцию open передается путь к программе, предваренный символом "|": open (MAIL, "|/usr/bin/mail $user") or die($!); print MAIL "Subject: Happy birthday!\n\n", "Hi, $user! Happy birthday!"; close MAIL;

      Ввод из программы

      Для приема данных из стандартного вывода другой программы нужно создать с помощью open соответствующий дескриптор файла (при этом программа будет запущена) и ввести из него данные. Для создания такого дескриптора вторым аргументом в функцию open передается путь к программе, после которого следует символ "|": open (LS, "/usr/bin/ls $dir |") or die($!); @dir_listing= <LS>; close LS;

      Переименование, удаление файла и изменение его атрибутов

      # переименовать файл rename $oldname, $newname or die($!); # удалить файлы (возвращает количество успешно удаленных файлов) unlink $this_file, $that_file, @and_whole_list_of_files; # изменить атрибуты файлов # (возвращает количество файлов у которых атрибуты были изменены) chmod 0755, @array_of_filenames; # изменить владельцев файлов ($uid и $gid должны быть числовыми) # (возвращает количество файлов у которых владельцы были изменены) chown $uid, $gid, @array_of_filenames; Запуск другой программы

      Для выполнения другой программы из скрипта используется функция system, аргументом которой является список argc[] (т.е. командная строка вывываемой программы, начинающаяся с имени самой программы). system $program_to_run, $argument1, $argument2, ...; Функция возвращает 0 при успешном завершении вызванной программы и X*256, если статус выхода программы был X.

      Работа со строками

      В этом пункте описаны некоторые полезные функции Перла для работы со строками (функции для работы с регулярными выражениями рассмотрены выше).

      Разбор строки

      Функция split разбивает скалярное значение, интерпретируемое как строка, на части, используя указанный разделитель, и возвращает результат в виде списка. @список = split; @список = split разделитель; @список = split разделитель, строка; @список = split разделитель, строка, лимит;

      Лимит указывает, что строка будет разбита не более, чем на лимит частей (иными словами, будут восприняты только первые лимит-1 разделителей; весь остаток будет возвращен в последнем элементе списка). Если лимит отсутствует, то все встретившиеся в строке разделители будут участвовать в разбиении.

      Если строка отсутствует, обрабатывается $_.

      Разделитель может быть регулярным выражением (заключается в слэши: /РВ/) или буквальной строкой (заключается в кавычки: 'строка'). Если разделитель отсутствует, то подразумевается /\s+/ ("один или более пробельных символов подряд"); т.е. split без аргументов экивалентен "split /\s+/, $_".

      Пример: # вывод списка всех пользователей системы с их идентификаторами UID open (PASSFILE, "/etc/passwd") or die($!); while (<PASSFILE>) { chomp; ($user, $junk, $uid) =split ':'; #ненужные элементы списка отбрасываются print "User $user has UID $uid\n"; };

      Формирование строки из списка элементов

      join join 'разделитель', @список;

      Функция join формирует скаляр-строку, состоящую из элементов списка, отделяя значения элементов друг от друга разделителем. $_ = join ' | ', "a", "b", "c"; print; #ВЫВОД: "a | b | c" # заменить разделители с двоеточия на запятую с пробелом $_ = join ', ' (split, ':');

      sprintf
      Функция sprintf работает так же, как в языке С.

      Поиск подстроки в строке

      index $позиция = index $строка, $подстрока, $начальная_позиция; $позиция = index $строка, $подстрока; Функция index возвращает позицию в строке, с которой начинается подстрока (имеется в виду первое вхождение подстроки, если их несколько). Если указана начальная позиция, то поиск начинается с этой позиции, иначе - с начала строки. Позиции в строке нумеруются, начиная с нуля. Если подстрока не найдена, функция возвращает -1. # последовательный поиск всех вхождений $lookfor в строку $string $pos = -1; while (($pos=index($string, $lookfor, $pos)) > -1) { print "Found at position $pos\n"; $pos++; }

      rindex

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

      Извлечение подстроки из строки в известной позиции $подстрока = substr $строка, $смещение, $длина; $подстрока = substr $строка, $смещение; Функция substr извлекает из строки подстроку длиной длина, начинающуюся с позиции смещение. Если длина не указана, то подстрока извлекается от смещения до конца строки. Позиции в строке нумеруются, начиная с нуля.

      Если смещение отрицательно, то оно отсчитывается не от начала, а от конца строки. Если длина отрицательна: длина=-N, то это значит, что извлекается подстрока такой длины, что она заканчивается за N символов до конца строки. # все нижеследующие операции присваивают переменной $_ значение "abc" $_ = substr "xyzabcqqqq", 3, 3; $_ = substr "xyzabcqqqq", 3, -4; $_ = substr "xyzabcqqqq", -7, 3; $_ = substr "xyzabcqqqq", -7, -4;

      Вставка/замена части строки в известной позиции

      Для вставки подстроки в строку или замены одной подстроки другой подстрокой используется функция substr в левой части оператора присвоения. В этом случае первый аргумент функции substr обязан быть скалярным выражением, которому можно присвоить значение - скалярной переменной, элементом массива или элементом хэша. Примеры (перед каждым примером предполагается, что $a="abcdef"): # 1) добавление подстроки "HELLO" в начало значения переменной $a substr($a,0,0) = "HELLO"; # в $a лежит "HELLOabcdef" # 2) замена второго и третьего символов в строке $_ словом "HELLO" substr($a, 1, 2) = "HELLO"; # в $a лежит "aHELLOdef" # 3) вставка слова "HELLO" между третьим и четвертым символами в строке $a substr($a, 3, 0) = "HELLO"; # в $a лежит "abcHELLOdef" # 4) замена последнего символа в строке $a словом "HELLO" substr($a, -1, 1) = "HELLO"; # в $a лежит "abcdeHELLO"

      Вышеприведенные операции можно понимать так: из переменной $a извлекается указанная подстрока, а потом вместо нее в этой же позиции вставляется слово "HELLO".

      Прочие функции # удаляет один символ с конца строки $a; возвращает удаленный символ chop $a; # удаляет с конца строки символ перевода строки, если он там есть, # иначе строка остается без изменений; # возвращает количество удаленных символов chomp $a; #возвращает длину строки $a $l = length $a; #переводит все символы строки $a в верхний регистр uc $a; #переводит первый символ строки $a в верхний регистр ucfirst $a; #переводит все символы строки $a в нижний регистр lc $a;

      Если аргументы вышеприведенных не указаны, подразумевается $_.

      Написание функций

      Функции описываются в любом месте скрипта с помощью конструкции sub имя_функции { тело_функции; } и вызываются обычным образом: имя_функции(аргумент1, аргумент2, ...); # со списком аргументов имя_функции(); # без аргументов Скобки при вызове написанных пользователем функций обязательны.

      Количество и тип аргументов не декларируются и могут быть любыми и различными при последовательных вызовах одной и той же функции; все аргументы при передаче в функцию объединяются в единый список; внутри функции все аргументы доступны через массив @_ в том порядке, в каком они были указаны при вызове функции. Если аргументов не было, то массив @_ пуст. Хэш, переданный в качестве аргумента, преобразуется в список (о взаимоотношениях списков и хэшей см. выше п. "Типы переменных. Хэши"). sub function1 { # абсолютно бессмысленная функция - просто иллюстрация, как взять аргументы my $x = shift; # при этом первый аргумент удаляется из списка @_ # если @_ пуст, то $x=undef my ($y,$z) = @_; # а здесь аргументы из списка @_ не удаляются #(если они там вообще есть, иначе $y=$z=undef) print "Our first argument is ", defined $x ? $x : "empty", "\n"; $y ||=1; # а $y и $z присвоим значения по умолчанию $z ||=1; } sub function2 { # жутко полезная функция # предполагается, что в качестве аргументов поступают скаляр $k и хэш %h; # функция возвращает $h{$k} my $k = shift; # если $k пусто или в списке аргументов ничего не осталось - вернуть undef и выйти (defined $k and @_) or return undef; my %h=@_; return $h{$k}; } # вызов функции (например): $value=function2("my_key",%hash);

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

      Каждая функция вызывается либо в скалярном, либо в списочном контексте; соответственным образом вызывающая программа интерпретирует возвращаемый функцией результат: # ф-я f() возвращает список @array=f(); # списочный контекст - все тривиально $x=f(); # скалярный контекст - в $x помещается длина возвращаемого списка, а сам он пропадает # ф-я s() возвращает скаляр @array=s(); # списочный контекст - список @array теперь состоит из одного возвращенного значения $x=s(); # скалярный контекст - все тривиально

      Для определения того, в каком контексте была вызвана функция, внутри нее используется оператор wantarray, возвращающий истину, если данная функция была вызвана в списочном контексте. Рассмотрим пример функции, которая возвращает список в списочном контексте и первый элемент списка - в скалярном. sub f { # здесь как-то создается список @array # ... return wantarray ? @array : $array[0]; } push @biglist, f(); # списочный контекст, т.к. вторым аргументом функции push ожидается список $first=f(); # скалярный контекст

      Внимание, распространенная ошибка! Если в функцию в качетсве аргументов переданы 2 массива: f(@ar1,@ar2), то внутри функции нет никаких способов определить, где в списке аргументов @_ кончается первый массив и начинается второй. Если внутри функции требуется различать эти массивы, то нужно передавать их в функцию в виде ссылок. Тоже самое касается и хэшей.

      Библиотека CGI.pm

      Строение скрипта






      Курс "Технологии Интернет"
      Кафедра КТС
      Максим Мамаев