Скалярные операции и функции
Скалярные операции и функции
Самая распространенная операция, выполняемая над скалярной переменной — присваивание, которое представляет собой способ задания значения этой переменной. Операция присваивания в Perl обозначается знаком равенства (почти как в С и ФОРТРАНе). С левой стороны ставится имя переменной, с правой — присваиваемое ей значение или выражение, при помощи которого это значение вычисляется, например:
$а =17; # присвоить переменной $а значение 17
$b = $а + 3; # присвоить $Ь текущее значение $а плюс 3 (20)
$b == $b * 2; # присвоить $b значение $b, умноженное на 2 (40)
Обратите внимание: в последней строке переменная $Ь используется дважды: один раз для получения значения (в правой части), а второй — для указания, куда поместить вычисленное выражение (в левой части). Это допустимый, надежный и довольно распространенный прием. Распространен он настолько, что через минуту мы увидим, как все это можно записать в сокращенном виде.
Возможно, вы заметили, что скалярные переменные всегда предваряются знаком $. В shell знак $ используют для получения значения, а при присваивании нового значения его не указывают. В Java и С этот символ
* Их количество ограничено числом 255. Надеемся, этого достаточно. 2. Скалярные данные
В этой таблице каждая операция имеет более высокий приоритет, чем перечисленные за ней, и более низкий приоритет, чем перечисленные перед ней.
Операции одного уровня приоритетов разрешаются в соответствии с правилами ассоциативности. Как и приоритет, ассоциативность определяет порядок выполнения операций, если две операции с одинаковым приоритетом пытаются манипулировать тремя операндами:
2 ** 3 ** 4 # 2 ** (3 ** 4) , или 2 ** 81, или около 2.41е24 72/12/3 # (72 / 12) / 3, или 6/3, или 2 30 / 6 * 3 # (30/6)*3, или 15
В первом случае операция ** имеет ассоциативность справа, поэтому круглые скобки подразумеваются справа. Операции * и / имеют ассоциативность слева, поэтому круглые скобки подразумеваются слева.
Преобразование чисел в строки и обратно
Если строковое значение используется как операнд в операции с числами (например, в операции сложения), Perl автоматически преобразует эту строку в эквивалентное числовое значение, как если бы оно было введено в виде десятичного числа с плавающей запятой*. Нечисловые окончания и начальные пробельные символы игнорируются, поэтому<< 12 3.4 5 f red" (с начальным пробелом) без какого-либо предупреждения преобразуется в 123. 45**. Самый крайний из подобных случаев — когда нечто, не являющееся числом, вообще без предупреждения преобразуется в нуль (как строка fred, которую мы использовали здесь как число).
Если же, наоборот, там, где должно быть строковое значение, вводится числовое (например, в операции конкатенации строк), это числовое значение конвертируется в строку, которая была бы выведена на экран вместо него. Например, если вы хотите конкатенировать строку х с результатом умножения 4 на 5, это можно записать как
"X" .(4*5) # то же самое, что "X" . 20, или "Х20"
(Помните, что круглые скобки заставляют сначала выполнить 4*5, а затем выполнять операцию конкатенации.)
Другими словами, вам не нужно (в большинстве случаев) беспокоиться о том, что указано в качестве операнда — строка или число, поскольку Perl выполняет все необходимые преобразования самостоятельно.
* Шестнадцатеричные и восьмеричные значения этому автоматическому преобразованию не подлежат. Для интерпретации таких значений следует использовать функции hex и oct.
** Если в командной строке не указана опция -w. В целях обеспечения безопасности всегда задавайте эту опцию.
Скалярные переменные
Имя переменной — это имя контейнера, который содержит одно или более значений. Имя переменной остается постоянным на протяжении всей программы, но значение (или значения), содержащееся в этой переменной, как правило, в ходе выполнения программы непрерывно изменяется.
Скалярная переменная содержит одно скалярное значение (представляющее собой число, строку или ссылку). Имена скалярных переменных состоят из знака доллара и буквы, за которой могут следовать еще несколько букв, цифр и знаков подчеркивания*. Строчные и прописные буквы различаются:
переменная $А и переменная $а — разные. Все буквы, цифры и знаки подчеркивания в имени переменной имеют значение. Так, переменная
$a_very_long_variable_that__end.s__in__l
отличается от переменной
$a_very_long_variable_that__ends_in_2
Имена переменных следует, как правило, подбирать так, чтобы они имели какой-то смысл в связи со значением переменной. Например, имя $xyzl23, вероятно, не очень описательно, в отличие от $line_length.
Скалярные операции и функции
Самая распространенная операция, выполняемая над скалярной переменной — присваивание, которое представляет собой способ задания значения этой переменной. Операция присваивания в Perl обозначается знаком равенства (почти как в С и ФОРТРАНе). С левой стороны ставится имя переменной, с правой — присваиваемое ей значение или выражение, при помощи которого это значение вычисляется, например:
$а =17; # присвоить переменной $а значение 17
$b = $а + 3; # присвоить $Ь текущее значение $а плюс 3 (20)
$b = $b * 2; # присвоить $b значение $b, умноженное на 2 (40)
Обратите внимание: в последней строке переменная $Ь используется дважды: один раз для получения значения (в правой части), а второй — для указания, куда поместить вычисленное выражение (в левой части). Это допустимый, надежный и довольно распространенный прием. Распространен он настолько, что через минуту мы увидим, как все это можно записать в сокращенном виде.
Возможно, вы заметили, что скалярные переменные всегда предваряются знаком $. В shell знак $ используют для получения значения, а при присваивании нового значения его не указывают. В Java и С этот символ
* Их количество ограничено числом 255. Надеемся, этого достаточно.
вообще опускается. Если вы постоянно присваиваете одной или нескольким переменным новые значения, то неминуемо будете делать ошибки. (Наше решение заключалось в том, чтобы прекратить писать программы на shell, awk и С, но для вас этот путь может быть неприемлем.)
Скалярное присваивание не только является операцией, его можно использовать и в качестве значения, аналогично тому как это делается в С. Другими словами, выражение $а=3 имеет значение, аналогично тому как имеет некоторое значение выражение $а+3. Значением является та величина, которая присваивается, т.е. $а=3 имеет значение 3. Хотя на первый взгляд это может показаться несуразным, использование присваивания как значения полезно, если вы хотите присвоить переменной промежуточное значение в выражении или просто скопировать одно значение в несколько переменных. Например:
$Ь = 4 + ($а =3); # присвоить 3 переменной $а, затем прибавить к 4,
# в результате чего $Ь получит значение 7 $d = ($с = 5); # скопировать 5 в $с, а затем и в $d $d = $с = 5; # то же самое, но без круглых скобок
Последнее выражение работает, потому что присваивание имеет ассоциативность справа.
Операции присваивания с вычислением
Выражения типа $ а == $а + 5 (где переменная стоит по обе стороны от оператора присваивания) встречаются довольно часто, поэтому в Perl применяется сокращенный метод записи операции изменения переменной — операция присваивания с вычислением. Почти все двоичные операции, с помощью которых вычисляются значения, имеют соответствующую форму с добавленным знаком равенства. Например, следующие две строки эквивалентны:
$а = $а + 5; # без операции присваивания с вычислением $а += 5; # с операцией присваивания с вычислением
Эквивалентны и эти строки:
$Ь = $Ь * 3;
$b *= 3;
В каждом из вышеприведенных случаев данная операция вызывает изменение существующего значения переменной определенным способом, а не просто замену этого значения результатом вычисления какого-то нового выражения.
Другой распространенной операцией присваивания является операция конкатенации строк:
$str = $str . " "; # добавить пробел к $str $str .= " "; # то же самое, но с операцией присваивания
Почти все двоичные операции, записанные таким образом, допустимы. Например, операция возведения в степень записывается как * * =. Так, $ а * * = 3 означает "возвести число, содержащееся в переменной $а, в третью степень и поместить результат обратно в $а".
Как и простая операция присваивания, эти операции также могут быть использованы в качестве значения, которым является новое значение переменной. Например:
$а = 3;
$b = ($а += 4); # $а и $b теперь равны 7
Автоинкремент и автодекремент
Казалось бы, для прибавления единицы к $а можно просто записать $а += 1, но Perl идет на шаг дальше и сокращает даже эту запись. Операция ++ (автоинкремент) прибавляет к своему операнду единицу и возвращает ин-крементированное значение, например:
$а += 1; # с операцией присваивания ++$а; # с префиксным автоинкрементом $d = 17;
$е = ++$d; # и $е, и $d теперь равны 18
Здесь операция ++ используется как префиксная, т.е. знак операции стоит слева от операнда. Автоинкремент можно записывать и в суффиксной форме (справа от операнда). В этом случае результатом выражения является старое значение переменной, которое она имела до инкрементирования. Например:
$с = 17;
$d = $с++; # $d равно 17, а $с равно 18
Поскольку значение операнда изменяется, операнд должен быть скалярной переменной, а не просто выражением. Не стоит рассчитывать, что ++16 получит значение 17, и нельзя сделать так, чтобы ++($а+$Ь) каким-то образом стало больше, чем сумма $а и $Ь.
Операция автодекремента (") похожа на операцию автоинкремента, но здесь не прибавляется единица, а вычитается. Как и операция автоинкремента, операция автодекремента имеет две формы — префиксную и суф-фиксную. Например:
$х = 12;
--$х; # $х теперь равно 11
$у = $х"; # $у равно 11, а $х - 10
Операции автоинкремента и автодекремента выполняются и над значениями с плавающей запятой. Автоинкрементирование переменной со значением 4,2 дает, как и следовало ожидать, 5,2*.
* Операция автоинкрементирования выполняется даже над строками. См. по данному вопросу книгу Programming Perl или man-страницу perlop(\).
Функции chop и chomp
Весьма полезной иногда бывает встроенная функция chop. Эта функция принимает один аргумент, указываемый в круглых скобках — имя скалярной переменной — и удаляет из строкового значения этой переменной последний символ. Например:
$х = "hello world";
chop($x); # $x теперь имеет значение "hello worl"
Обратите внимание: значение аргумента здесь меняется, отсюда и требование к наличию скалярной переменной, а не просто скалярного значения. Писать chop (' suey'), чтобы превратить аргумент в 'sue', не имеет смысла, потому что места для хранения этого значения нет. Кроме того, можно ведь и просто написать: ' sue '.
Возвращаемое значение для этой функции — отброшенный символ (в приведенном выше примере с "hello world" это буква d). Следующий код, очевидно, неверен:
$х == chop($x); # НЕВЕРНО: заменяет $х ее последним символом chop($x); # ВЕРНО: как и выше, удаляет последний символ
Если в функции chop задать пустую строку, то она ничего не сделает и ничего не возвратит, не выдавая сообщения об ошибке и вообще никак не реагируя*. Большинство операций в Perl имеют разумные граничные условия; другими словами, вы можете использовать их в пределах накладываемых ограничений и за ними, причем часто без какой-либо реакции с их стороны. Некоторые утверждают, что это один из фундаментальных недостатков Perl, а другие пишут первоклассные программы, нисколько не утруждая себя заботой о соблюдении этих ограничений. Вам решать, к какому лагерю присоединяться.
При усечении уже усеченной строки отбрасывается еще один символ. Например:
$а = "hello world\n";
chop $a; # теперь $а имеет значение "hello world" chop $a; # оп-ля! теперь $а имеет значение "hello worl"
Если вы не уверены в том, есть ли в конце переменной символ новой строки, можете использовать несколько более безопасную операцию chomp, которая удаляет только символ новой строки**, например:
$а == "hello world\n";
chomp ($a); # теперь $а имеет значение "hello world" chomp ($a); # ага! никаких изменений в $а не произошло
* Если вы не используете соответствующий здравому смыслу ключ -w.
** Или иное значение, которое задано переменной $ \ в качестве разделителя входных записей.
Интерполяция скаляров в строках
Если строковый литерал взят в двойные кавычки, в нем необходимо выполнить интерполяцию переменных (помимо проверки на наличие управляющих последовательностей с обратной косой). Это значит, что строка просматривается на предмет наличия имен скалярных переменных* — а именно комбинаций знака доллара с буквами, цифрами и знаками подчеркивания. Если ссылка на переменную имеется, она заменяется текущим значением этой переменной (или пустой строкой, если значение переменной еще не присвоено). Например:
$а = "fred";
$b = "some text $a"; # $b имеет значение "some text fred" $c = "no such variable $what"; # $c имеет значение "no such variable "
Текст, который заменяет переменную, не просматривается, т.е. даже при наличии в нем знаков доллара никакие дальнейшие замены не производятся:
$х = *$fred'; # буквально знак доллара и слово "fred" $у = "hey $х"; # значение — 'hey $fred'; двойной подстановки нет
Если необходимо предотвратить подстановку значения вместо имени переменной, необходимо либо изменить эту часть строки так, чтобы она стояла в одинарных кавычках, либо поставить перед знаком доллара обратную косую, которая отменяет его специальное значение:
$fred = 'hi';
$barney = "a test of " . '$fred'; # буквально: 'a test of $fred' $barney2= "a test of \$fred"; # то же самое
В качестве имени переменной будет взято самое длинное из возможных имен, имеющих смысл в этой части строки. Это может вызвать проблему, если вы хотите сразу же после заменяемого значения дать какой-то постоянный текст, который начинается с буквы, цифры или знака подчеркивания. Проверяя строку на предмет наличия имен переменных, Perl посчитал бы эти символы дополнительными символами имени — а как раз этого вам и не нужно. В Perl имеется разделитель имени переменной. Просто заключите имя переменной в фигурные скобки. Другой вариант — завершить эту часть строки и начать другую часть строки знаком операции конкатенации:
$fred = "pay"; $fredday = "wrong!";
$barney = "It's $fredday"; # не день зарплаты payday, a "It's wrong!" $barney = "It's ${fred}day"; # теперь $barney получает значение "It's payday" $barney2 = "It's $fred"."day"; # еще один способ $barney3 = "It's " . $fred . "day"; # и еще один
* И переменных-массивов, но этот вопрос мы будем рассматривать в главе 3 Массивы и списочные данные.
Для изменения регистра букв, задействованных в интерполяции переменных, можно использовать специально предназначенные для этого строковые управляющие последовательности*. Например:
$bigfred = "\Ufred"; # $bigfred имеет значение "FRED"
$fred = "fred"; $bigfred = "\U$fred"; # то же самое
$capfred = "\u$fred"; # $capfred имеет значение "Fred"
$barney = "\LBARNEY"; # $barney теперь имеет значение "barney"
$capbarney = "\u\LBARNEY"; # $capbarney теперь имеет значение "Barney"
$bigbarney = "BARNEY"; $capbarney = "\u\L$bigbarney"; # то же самое
Как видите, изменяющие регистр строковые управляющие последовательности хранятся до тех пор, пока не окажут свое воздействие, поэтому, несмотря на то, что первая буква слова barney не стоит непосредственно за символами \и, она становится прописной благодаря воздействию \и.
Термин "интерполяция переменных" иногда заменяют термином "интерполяция двойных кавычек", потому что интерполяция выполняется в строках, заключенных в двойные кавычки. (А также в строках, заключенных в обратные кавычки, которые мы рассмотрим в главе 14.)