Анимация
JavaScript
|
Главная Библионтека Лучше всего делать это в подпрограмме init words (); мы уже работаем в ней с файлом wordlist. Perl-операция -м возвращает значение, равное количеству дней, прошедшему с момента изменения файла или дескриптора файла, поэтому нам нужно просто посмотреть, превышает ли это значение число семь для дескриптора файла wordslist: sub init words ( open (WORDSLIST, "wordslist") I I die "cant open wordlist: $"; if (-M WORDSLIST >= 7.0) ( # в соответствии с бюрократическими правилами die "Sorry, the wordslist is older than seven days. ",• while (5name = <WORDSLIST>) ( chomp ($name) ; $word = <WORDSLIST> ; chomp ($word) ; $words{$name} = $word; close (WORDSLIST) die "couldnt close wordlist: $",- Значение -м wordslist сравнивается со значением 7. Если оно больше, то мы, выходит, нарушили правила. Здесь мы видим новую операцию, операцию die, которая одним махом выводит сообщение на экран" и прерывает программу. Остальная часть программы изменений не претерпевает, поэтому в целях экономии бумаги мы ее повторять не будем. Помимо определения "возраста" файла мы можем узнать имя его владельца, размер, время последнего доступа к нему и все остальные сведения, хранимые системой о каждом файле. Более подробно об этом написано в главе 10. Как предупредить пользователя, если он соился с пути Давайте посмотрим, как можно заставить систему посылать сообщение электронной почты всякий раз, когда пользователь указывает свое секретное слово неверно. Нам нужно модифицировать только подпрограмму good word () (сказывается преимущество модульности языка Perl), потому что вся необходимая информация находится у нас там. Почтовое сообщение будет послано вам в том случае, если вы вставите свой адрес электронной почты там, где в программе записано YOURAD-DRESS HERE. Все, что нам нужно для этого сделать, это непосредственно перед тем, как возвращать из подпрограммы О, создать дескриптор файла, который фактически будет являться процессом (mait): sub good word ( my($somename,$someguess) = Q ; # перечислить параметры $somename =~ s/\W.* ; # удалить все символы, стоящие после # первого слова Если точнее, то в дескриптор файла stderr, но обычно это и означает терминал $somename =~ tr/A-Z/a-z/; # перевести все символы в нижний регистр if ($somename eq "randal") { # не нужно угадывать return 1; # возвращаемое значение - true ) elsif (($words{$somename} I I"groucho") eq $someguess) { return 1; # возвращаемое значение - true } else { open MAIL,"mail YOUR ADDRESS HERE" ; print MAIL "bad news: $somename guessed $someguess\n"; close MAIL; return 0; # возвращаемое значение - false Первый новый оператор здесь - open, в начале второго аргумента которого стоит оператор канала (). Он указывает, что мы открываем процесс, а не файл. Поскольку оператор канала находится перед именем команды, мы открываем процесс так, чтобы можно было осуществить в него запись. (Если поставить оператор канала в конец, а не в начало, то можно будет читать выходную информацию команды.) Следующий оператор, print, выбирает для вывода не stdout*, а дескриптор файла, стоящий между ключевым словом print и подлежащими выводу на экран значениями. Это значит, что сообщение в конечном итоге станет входной информацией для команды mail. Наконец, мы закрываем дескриптор файла, в результате чего запускается программа mail и передает свои данные. Чтобы соблюсти все формальности, мы могли бы посылать не только ошибочный, но и правильный ответ, но тогда тот, кто заглядывает нам через плечо (или прячется в системе электронной почты), когда мы читаем сообщения, получил бы слишком много полезной информации. Perl может также открывать дескрипторы файлов, вызывать команды с необходимыми аргументами, даже порождать копию текущей программы и выполнять две (или более) копии программы одновременно. Обратные кавычки (как в shell) дают возможность получать результаты работы команды как данные. Все это описывается в главе 14, так что читайте дальше. Несколько файлов секретных слов в текущем каталоге Давайте слегка изменим способ определения имени файла секретных слов. Вместо файла с именем wordslist будем искать в текущем каталоге нечто, заканчивающееся на .secret. Попросим shell выдать краткий перечень таких имен. echo *.secret Говоря техническим языком - выбранный в текущий момент дескриптор файла. Об этом, однако, мы поговорим позже. Как вы скоро увидите, Perl применяет похожий синтаксис имен с использованием метасимволов. Еще раз вернемся к определению подпрограммы init words (): sub init words { while ( defined($filename = glob("*.secret")) ) { open (WORDSLIST, $filename) I I die "cant open wordlist: $"; if (-M WORDSLIST >= 7.0) { while ($name = <WORDSLIST>) { chomp $name; $word = <WORDSLIST>; chomp $word; $words($name1 = $word; close (WORDSLIST) die "couldnt close wordlist: Сначала мы поместили в новый цикл while основную часть подпрограммы из предыдущей версии. Новый элемент здесь - функция glob. По историческим причинам она называется filename glob. Эта функция работает почти так же, как <stdin>: при каждом обращении к ней она возвращает очередное значение из списка имен файлов, которые соответствуют образцу shell, в данном случае * . secret. Если таких имен файлов нет, возвращается пустая строка*. Таким образом, если текущий каталог содержит файлы fred. secret и barney, secret, to при первом выполнении цикла while значением переменной Sfilename будет barney. secret (имена даются по алфавиту). При втором выполнении цикла значением $filename будет fred. secret Поскольку при третьем вызове функции glob она возвращает пустую строку, то третий проход не делается, так как цикл while интерпретирует это значение как "ложь", что приводит к выходу из подпрограммы. В ходе выполнения цикла while мы открываем файл и проверяем, достаточно ли давно он обновлялся (с момента последнего изменения должно пройти не более семи дней). С этими достаточно новыми файлами мы работаем так же, как и раньше. Отметим, что в отсутствие файлов, имена которых совпадали бы с шаблоном *.secret и "возраст" которых не превышал бы семи дней, подпрограмма завершится, не поместив ни одного секретного слова в массив %words. Это значит, то всем придется пользоваться словом groucho. Прекрасно. (В реальном коде перед выходом из подпрограммы следовало бы ввести операцию проверки количества элементов в массиве %words - и при неудовлетворгггель-ном результате выполнить функцию die. Обратите внимание на функцию keys, когда мы дойдем до определения хешей в главе 5.) Да-да, опять undef 0 1 2 3 4 5 6 7 8 9 10 11 12 13 [ 14 ] 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |