Perl: прием входных данных и проверка их достоверности, модули расширения.

В приведенном ниже сценарии объединены многие уже рассмотренные нами конструкции Perl, включая использование подпрограммы, нескольких постфиксных операторов if и цикла for. Сама программа — это просто "обертка", в которую "завернута" основная функция getstring, обеспечивающая проверку достоверности входных данных. Эта функция приглашает пользователя ввести строку, удаляет замыкающий символ новой строки и проверяет, не является ли введенная строка нулевой. После приема нулевой строки пользователю предлагается повторить ввод, но после трех неудачных попыток сценарий "умоет руки".

#!/usr/bin/perl

$maxatt = 3; # Максимальное число попыток ввести корректные данные

sub get_string {

my ($prompt, $response) = shift;

# Пытаемся прочитать входную строку до $maxatt раз for (my $attempts = 0; $attempts < $maxatt; $attempts++) { print "Пожалуйста, попытайтесь еще раз.\п" if $attempts; print "$prompt: "; $response = readline(*STDIN); chomp($response); return $response if $response; }

die "Слишком много неудачных попыток ввести данные"; }

# Прием имен с помощью функции get_string и перевод в прописные буквы $fname = uc

$lname = uc get_string "Фамилия"; printf "Полное имя: $fname $lname\n";

Результат выполнения этого сценария таков.

$ peri validate Имя:    John Ball

Фамилия: Park

Полное имя:  JOHN BALL PARK

Функция getstring и цикл for иллюстрируют использование оператора ту в создании переменных локальной области видимости. По умолчанию все переменные в Perl являются глобальными. Список локальных переменных для функции getstring инициализируется с помощью одного скаляра, получаемого из массива аргументов функции. Переменные в списке инициализации, которые не имеют надлежащего значения (в данном случае это переменная $response), остаются неопределенными.

Значение *STDIN, переданное функции чтения строк, имеет "всеядный" тип type-glob, который считается слабым местом в языковом проектировании. Из соображений самосохранения, лучше не ломайте голову над тем, что он (этот тип) в действительности означает. Возможно, вас удовлетворит такое короткое пояснение: в Perl дескрипторы файлов не относятся к типам данных "первого класса", поэтому в общем случае для передачи их функциям в качестве аргументов необходимо перед их именами ставить символ "звездочка".

В присваиваниях для переменных $fname и $lname обе функции и с (convert to uppercase — означает преобразовать в прописные буквы) и getstring вызываются без использования круглых скобок. Поскольку в данном случае функциям передается один единственный аргумент, здесь нет никакой неоднозначности, а потому "экономия" никак не навредила.

 

Использование языка Perl в качестве фильтра

Язык Perl можно использовать без сценария — просто введя отдельные выражения в командную строку. Это позволяет быстро выполнить преобразования текста и "объявить" устаревшими такие программы фильтрации, как sed, awk и tr.

Ключ командной строки -ре дает возможность циклически обработать поток STDIN, вычислить простое выражение в каждой строке и вывести результат. Например, команда

ubuntu$ peri -ре 1s#/bin/sh$#/bin/bash#1  /etc/passwd

root:x:0:0:root:/root:/bin/bash

daemon:x:1:1:daemon:/usr/sbin:/bin/bash

заменяет текст /bin/sh в конце строк файла /etc/passwd текстом /bin/bash, выводя трансформированный файл passwd в поток STDOUT. Возможно, вы привыкли к тому, что оператор подстановки текста использует в качестве разделителей слеши (например, s/f oo/bar/), но Perl позволяет применять любой символ. Здесь как искомый текст, так и текст замены содержат слеши, поэтому в данном случае в качестве разделителя проще использовать символ "#". Предпочитая парные разделители, вы должны применять их в количестве четырех вместо "обычных" трех, например s (foo) (bar).

Perl-ключ -а устанавливает режим автоматического разбиения, в котором входные строки разбиваются на поля, сохраняемые в массиве @F. Разделителем полей по умолчанию служит пробел, но с помощью ключа -F вы можете установить другой шаблон разделителя. Режим авторазбиения удобно использовать вместе с ключом -р или его вариантом запрещения автовывода -п. Например, в приведенных ниже строках используется вариант команды peri -апе, чтобы отформатировать результат работы двух вариантов команды df. В третьей строке выполняется команда join, которая объединяет два набора полей в поле Filesystem, создавая составную таблицу, включающую поля, "вытащенные" из обеих версий результата команды df.

suse$ df -h  |  peri -ane   'print join("\t",  @F[0..4]),   "\nni  > tmpl suse$ df -i   |  peri -ane   'print join("\t",   @F[0,1,4]),   "\n"'   > tmp2 suse$    join tmpl  tmp2

 

Вариант сценария без временных файлов выглядит следующим образом.

#!/usr/bin/perl

for (split(Лп/, 'df -h')) {

@F — split;

$h_part{$F[0]} = [ @F[0..4] ]; } for (split (An/, 1df -i') {

@F = split;

print join("\t", @{$hj?art{$F[0]}}, $F[1], $F[4]), "\n"; }

Истинно бесстрашные программисты могут использовать ключ -i вместе с ключом -ре, чтобы редактировать файлы "прямо по месту": Perl считывает содержимое файлов, передает их строки на редактирование и сохраняет результаты в исходных файлах. Вместе с ключом -i можно предоставить шаблон, который укажет, как именно резервировать оригинальную версию каждого файла. Например, вариант -i.bak позволит сохранить резервную копию файла passwd в виде файла passwd.bak. Но будьте осторожны — если вы не предоставите образец резервирования, резервная копия не будет создана совсем. Обратите внимание на то, что ключ -i и предоставляемый вами суффикс не разделяются пробелом.

 

Модули расширения для Perl

Всеобъемлющая сеть архивов Perl (Comprehensive Perl Archive Network — CPAN) — это обширное хранилище пользовательских Рег1-библиотек (cpan. org). Инсталляция новых модулей значительно облегчается командой cpan, которая действует во многом подобно открытому консольному менеджеру yum или менеджеру управления пакетами APT, "специализирующимся" на модулях Perl. Если вы работаете в системе Linux, поинтересуйтесь, есть ли в вашем дистрибутиве модуль, который вы собираетесь использовать в качестве стандартного средства, — намного проще инсталлировать однажды пакет системного уровня, а затем позволить системе самой периодически заботиться о собственных обновлениях.

Если в системе нет команды cpan, можно "пойти другим путем" и попытаться выполнить команду peri -MCPAN -е shell.

$ sudo peri -MCPAN -e shell

cpan shell — CPAN exploration and modules installation (vl.9205)

ReadLine support available (maybe install Bundle::CPAN or Bundle::CPANxxl?)

cpan[1]> install Class::Date

CPAN: Storable loaded ok (v2.18)

CPAN: LWP: :UserAgent loaded ok (v5.819)

CPAN: Time::HiRes loaded ok (vl.9711)

… several more pages of status updates ...

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

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

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

 

Комментарии (0)

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.