Анимация
JavaScript


Главная  Библионтека 

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

chomp (Sguess);

while ($guess ne $3ecretword) (

print "Wrong, try again. What is the secret word? "; $диезз = <STDIN> ; chomp ($диезз) ;

Как видите, эта программа уже довольно далека от простенькой Hello, World. Хотя она и очень мала, но вполне работоспособна, причем краткость программы достигается весьма небольшими усилиями. В этом - стиль Perl

В Perl имеется все, что необходимо для работы с регулярными выражениями, т.е. он предоставляет все возможности, которые обеспечивает любая стандартная утилита UNIX (и даже некоторые нестандартные). Способ сопоставления строк, используемый в Perl, является чуть ли не самым быстрым сравнительно с другими языками, поэтому производительность системы при выполнении Perl-программ никоим образом не снижается. (Написанная на Perl grep-подобная программа часто превосходит прилагаемую поставщиками программу гер на С*. Это значит, что grep не выполняет толком даже единственную свою задачу.)

Справедливость для всех

Итак, теперь я могу ввести Randal, randal или Randal L. Schwartz, но как быть с остальными? Барни должен вводить в точности barney (ему нельзя ввести даже пробел после barney).

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

Сначала - операция подстановки: мы хотим взять содержимое переменной $name, найти первый специальный (не использующийся в словах) символ и убрать все символы, начиная с того места, где он стоит, и до конца строки. Искомое регулярное выражение имеет вид /\w.*/. Здесь \w обозначает специальный символ (т.е. все кроме буквы, цифры и знака подчеркивания), а . * обозначают любые символы с этого места до конца строки. Чтобы убрать эти символы, нужно взять ту часть строки, которая совпадает с рассматриваемым регулярным выражением, и заменить ее пустой строкой:

$name =~ 3/\W.* ;

Мы используем ту же операцию =~, что и раньше, но справа у нас теперь стоит операция подстановки - буква s, за которой следуют заключенные между двумя косыми регулярное выражение и строка. (Строка в данном

Однако GNU-версия утилиты cgrcp выполняет эту операцию гораздо быстрее, чем Peil



примере - это пустая строка между второй и третьей косыми.) Эта операция выглядит и выполняется во многом так же, как операции подстановки в программах-редакторах.

Теперь для того, чтобы перевести все оставшиеся символы в нижний регистр, мы преобразуем эту строку с помощью операции tr*. Она очень похожа на UNIX-команду tr, т.е. получает список искомых символов и список символов, которыми искомые символы заменяются. В нашем примере мы, чтобы перевести содержимое переменной $name в нижний регистр, используем такую запись:

$name =~ tr/A-Z/a-z/;

Между косыми заключены списки искомых и заменяющих их символов. Дефис между буквами А и z обозначает все символы, находящиеся между ними, т.е. у нас есть два списка, в каждый из которых включено по 26 символов. Когда tr находит символ из какой-либо строки первого списка, он заменяется соответствующим символом из второго списка. В результате все прописные буквы А, В, С и т. д. становятся строчными**.

Объединяя эти строки с остальной частью программы, получаем:

# /usr/bin/perl %words = qw(

fred camel

bamey llama

betty alpaca

wilma alpaca

print "What IS your name? "; $name = <STDIN>; chomp ($name);

$original name = $name; # сохранить для приветствия

$name =~ s/\W.* ; # избавиться от всех символов, следующих после первого слова

$пагае =~ tr/A-Z/a-z/; # перевести все в нижний регистр if ($name eq "randal") [ # теперь можно так сравнить

print "Hello, Randal How good of you to be hereXn";

) else (

print "Hello, $original name \n"; #обычное приветствие $secretword = $words{$name}; # получить секретное слово

if ($secretword eq "") ( # не найдено

$secretword = "groucho"; # конечно, можно использовать

print "What IS the secret word? "; $guess = <STDIN>; chomp ($guess);

while ($guess ne $secretword) (

Символы с диакритическими знаками такому переводу не поддаются Подробности см на man-странице perllocale(\) в версии языка Peil5 004

Специалисты заметят, что мы также могли написать нечто вроде s/(\S*) .*/\L$l/, чтобы сделать все это за один присест, но специалисты, вероятно, не будут читать данный раздел



print "Wrong, try again. What is the secret word? $guess = <STDIN>; chomp ($guess);

Обратите внимание на то, что сопоставление с регулярным выражением для слова Randal вновь выполняется с помощью обычной операции сравнения. Дело в том, что и Randal L. Schwartz, и Randal после подстановки и перевода превращаются в randal. Для всех остальных пользователей справедливо то же самое, потому что Fred и Fred Flinstone превращаются ВО fred; Barney Rubble и Barney, the little guy - в barney и т.д.

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

Отметим, однако, что в процессе обработки имени (т.е. при его модификации, необходимой для проведения операции сравнения и поиска соответствия в таблице) первоначально введенное имя уничтожается. Поэтому перед обработкой имени программа сохраняет его в переменной $original name. (Как и имена в С, имена переменных в Perl состоят из букв, цифр и знаков подчеркивания, причем длина их практически не ограничена.) Благодаря этому мы впоследствии сможет ссылаться на $original name.

В Perl имеется много способов, позволяющих проводить анализ и изменение символов в строках. С большинством из них вы познакомитесь в главах 7 и 15.

Повышение степени модульности

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

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

Давайте создадим для нашей маленькой, но быстро растущей программы подпрограмму good word, которая будет принимать имя и вариант слова и возвращать значение "истина", если это слово введено правильно, и "ложь", если слово набрано неправильно. Определение такой подпрограммы выглядит следующим образом:



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