Российский государственный гуманитарный университет
Опубликован: 15.08.2003 | Доступ: свободный | Студентов: 6518 / 1489 | Оценка: 3.91 / 3.79 | Длительность: 06:55:00
Лекция 3:

Введение в программирование на Perl

< Лекция 2 || Лекция 3: 1234 || Лекция 4 >

Регулярные выражения (сопоставление с образцом)

Самым интересным средством Perl является механизм регулярных выражений, сравнение с образцом и подстановки, которые он унаследовал от таких типичных для Unix-систем утилит, как awk и sed.

Операция сопоставления с образцом задается как "=~":

$query =~ /target/;

В данном случае в скаляре $query отыскивается подстрока " target ". С операцией "=~" связано два действия по умолчанию. Во-первых, операция сопоставления в полной форме будет записана как

$query =~ m/target/;

То есть перед шаблоном используется префикс m. Во-вторых, если опустить $query, то образец будет сопоставляться с содержанием системной переменной $_:

/target/;

Операция "=~" возвращает значение "истина"( true ), если образец был найден, и "ложь"( false ), в противном случае. Из этого следует, что данную операцию можно использовать в операторах ветвления:

if($query =~ /target/)
{
print $query;
}

В данном случае, если образец содержится в $query, то запрос печатается, не содержится — пропускается при печати.

При сопоставлении с образцом одновременно осуществляется разбор запроса: шаблон попадает в переменную $_, часть строки до найденного шаблона — в $`, а после образца — $'. Но для программирования разбора данных из формы больше подойдет следующий пример ( perlexp1.htm ):

http://intuit.ru/scripts/
script?n1=v1&n2=v2&n3=v3
...
($v1,$v2,$v3) = ($query =~ 
/^n1=(.+)&n2=(.+)&n3=(.+)$/);
print $v1,$v2,$v3;

В переменные $v1 — $v3 будут записаны значения полей n1-n3, соответственно. При этом символ "^" означает, что весь шаблон должен стоять вплотную к началу строки. Символ "$" в конце шаблона означает, что шаблон должен распространяться на всю строку до конца. Символ "." означает любой символ, входящий в таблицу символов, "+" означает любое количество этих символов, но не менее одного.

Еще более мощным средством является подстановка, которая базируется на механизме сопоставления с образцом. Для ее осуществления следует использовать префикс s%

$query =~ s/intuit/ruru/;

В данном случае, если в строке будет найден шаблон intuit, он будет заменен на ruru. Наиболее очевидной областью применения подстановки является перекодировка запросов form-urlencoded:

$query =~ s/%(.{2})/pack('c',hex($1))/eg;

Спецсимволы и символы из второй половины таблицы ASCII при передаче трансформируются в шестнадцатеричные описания байтов (две цифры), следующие после символа "%".

Управление потоком вычислений

Под управлением потоком вычислений понимают способность программы в зависимости от условий выполнять те или иные части кода и повторять различные части кода. Для этой цели в Perl включены такие операторы как goto, next, last, redo, if, while, for, foreach и другие.

Оператор GOTO

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

while()
{
if(/the end/) {goto out;};
}
out: print "the_end\n";

В данном случае выход из цикла осуществляется по оператору goto. Вслед за всеми современными учебниками, напомним, что использование goto — это плохой стиль программирования. Метка в Perl задается как строка, за которой вплотную следует символ двоеточия(":").

Оператор while

В нашем примере встретилось еще несколько конструкций управления потоком вычислений. Первая из них — оператор while. While определяет цикл, который исполняется до тех пор, пока значение выражения, указанного в качестве аргумента оператора while, — "истина". Пример:

while(not($line =~ /the_end/))
{
$line = <>;
print "No\n";
}
print "the_end\n";

В данном случае оператор goto не используется. Выход из цикла осуществляется по условию вхождения подстроки the_end в строку ввода. Вхождение проверяется путем сопоставления с образцом. Входная строка считывается из стандартного ввода (операция <> ).

Оператор for

Оператор for — это традиционный оператор цикла. Типовая схема применения данного оператора может быть показана на следующем примере:

for($i=0;$i<CONTENT_LENGTH;$i++)
{
$query[$i] = getc;
}
$q = join (@query);
print $q;

Здесь данные в цикле считываются посимвольно из стандартного потока ввода в массив @query. Число символов, которые нужно считать, определяется переменной окружения CONTENT_LENGTH. После завершения ввода массив объединяется в строку $q при помощи функции join. Наиболее типичной ошибкой при использовании оператора for является отсутствие символа " $ " у переменной цикла. Все три аргумента оператора for могут быть выражениями соответствующего типа.

Оператор foreach

Оператор foreach позволяет организовать цикл путем перебора элементов списка. В качестве такого списка можно использовать массив:

foreach $arg (@ARGV)
{
print $arg;
}

В данном случае переменная цикла $arg пробегает по всем аргументам командной строки скрипта, которые задаются встроенным массивом @ARGV. Аналогично можно пройти и по всем переменным окружения:

foreach $arg (keys %ENV)
{
print "$arg:$ENV{$arg}\n";
}

Отличие данного примера от предыдущего заключается в том, что переменные окружения представляют собой хеш. Поэтому сначала получаем массив ключей (имен переменных окружения), переменная $arg пробегает по этому массиву, и в цикле печатаются пары "имя переменной — значение переменной".

Оператор if

После goto и операторов цикла следует остановиться на операторе if. Данный оператор позволяет организовать ветвление программы или, как это еще называют, условное исполнение отдельных ее частей. Примером может служить скрипт обработки данных, которые могут доставляться как по методу GET, так и по методу POST:

if ($ENV{REQUEST_METHOD} =~ /POST/)
  {
  read STDIN,$query,$ENV{CONTENT_LENGTH};
  }
else
  {
  $query = $ENV{QUERY_STRING};
  }

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

Оператор next

Если оператор goto не применять (концепция структурного программирования), то при работе с циклами нужно обрабатывать ситуации пропуска конца тела цикла и досрочного выхода из тела цикла. Пропуск операторов конца тела цикла осуществляется при помощи оператора next:

foreach $arg (@strings)
{
if(!($ENV{REMOTE_HOST} =~ /\.intuit\.ru/)) 
  next;
print $arg;
}

Здесь фрагмент скрипта печатает значения массива @string, только если скрипт вызван с компьютера из домена intuit.ru. Машина пользователя будет прописана в этом домене только в том случае, если она прописана в обратной зоне, т.е. есть не только прямое соответствие "имя — IP-адрес", но и обратное "IP-адрес — имя". При этом сервер должен выполнять поиск доменных имен компьютеров пользователей по их IP-адресам (режим nslookup ).

Оператор last

Досрочный выход из тела цикла производится по оператору last. Обычно такой выход осуществляется по некоторому событию:

open IN,"<cont.txt";
while()
  {
  if($_ =~ /index\.htm/) last;
  #разбор строки
  }
close IN;

В данном примере скрипт считывает строки из файла счетчика посещений. Если в строке встречается имя файла "index.htm", то происходит досрочный выход из цикла.

Оператор redo

Оператор redo применяется для повторения последней итерации цикла. Например, если есть вложенные циклы while, которые выполняют одинаковые последовательности операторов, то внутренний из них можно заменить на оператор if с redo.

< Лекция 2 || Лекция 3: 1234 || Лекция 4 >