Назад | Вперед |
Требуется закрепить за скалярной переменной значение по умолчанию, но лишь в том случае, если оно не было задано ранее. Довольно часто требуется, чтобы стандартное значение переменной жестко кодировалось в программе, но его можно было переопределить из командной строки или переменной окружения.
Воспользуйтесь оператором || или ||=, работающим как со строками, так и с числами:
# Использовать $b, если. Значение $b истинно, и $с в противном случае $а = $b || $с; # Присвоить $х значение $у. носишь в том случае, # если $х не является истинной $х ||= $у;
Если ваша переменная может принимать значения Одни "0", воспользуйтесь функцией defined
#использоватъ $b если значение $b определено , и $с в противном случае $а =defined($b) ? $b : $c
Главное отличие между этими двумя приемами (defined и ||) состоит, прежде всего, в том, что именно проверяется - определенность или истинность, В мире Perl три определенных значения являются ложными: 0, "0" и "". Если ваша переменная содержит одну из этих величин, но вы не хотите изменять ее, 11 не подойдет - приходится выполнять неуклюжие проверки с defined. Часто бывает удобно организовать программу так, чтобы принималась в расч т истинность или ложность переменных, а не их определенность.
В отличие от других языков, где возвращаемые значения ограничиваются 0 и 1, оператор || Perl обладает более интересным свойством: он возвращает первый (левый) операнд, если тот имеет истинное значение; в противном случае возвращается второй операнд. Оператор && ведет себя аналогично (для второго выражения), но этот факт используется реже. Для операторов несущественно, что представляют собой их операнды - строки, числа или ссылки; подойдет любое скалярное значение. Они просто возвращают первый операнд, из-за которого все выражение становится истинным или ложным. Возможно, это расходится с возвращаемым значением в смысле булевой алгебры, но такими операторами удобнее пользоваться.
Это позволяет установить значение по умолчанию для переменной, функции или более длинного выражения в том случае, если первый операнд не подходит. Ниже приведен пример использования ||, в котором $foo присваивается либо $bar, либо, если значение $bаr ложно, - строка "DEFAULT VALUE":
$foo = $bar || "DEFAULT VALUE";
В другом примере переменной $dir присваивается либо первый аргумент командной строки программы, либо "/tmp", если аргумент не указан:
$dir = shift(@ARGV) || "/tmp";
То же самое можно делать и без изменения @ARGV:
$dir = $ARGV[0] || "/tmp";
Если 0 является допустимым значением $ARGV[0], использовать || нельзя, потому что вполне нормальное значение будет интерпретировано как ложное. Приходится обращаться к тернарному оператору выбора:
$dir = defined($ARGV[0]) ? shift(@"ARGV) : "/tmp";
To же можно записать и иначе, со слегка измененной семантикой:
$dir = @ARGV ? $ARGV[0] : "/tmp";
Мы проверяем количество элементов в @ARGV. В условии оператора выбора (?:) @ARGV интерпретируется в скалярном контексте. Значение будет ложным лишь при нулевом количестве элементов, в этом случае будет использоваться "/tmp". Во всех остальных ситуациях переменной (когда пользователь вводит аргумент) будет присвоен первый аргумент командной строки.
Следующая строка увеличивает значение %count, при этом в качестве ключа используется значение $shell, а если оно ложно - строка "/bin/sh".
$count{ $shell || "/bin/sh" }++;
В одном условии можно объединить несколько альтернативных вариантов, как показывает следующий пример. Результат совпадает с первым операндом, имеющим истинное значение.
# Определить имя пользователи всистеме UNIX $user = $ENV{USER} || $ENV{LOGNAME} || getlogin() || (getwuid($<))[0] || "Unknown uid number $<";
Оператор && работает аналогично; он возвращает первый операнд, если этот операнд ложен. В противном случае возвращается второй операнд. Поскольку ложные значения представляют интерес существенно реже, чем истинные, это свойство используется не так часто. Одно из возможных применений продемонстрировано в рецепте 8.13.
Оператор присваивания || = выглядит странно, но работает точно так же, как и остальные операторы присваивания. Практически для всех бинарных операторов perl $var ОР= value означает $var = $var op value; например, $а += $Ь-тоже, что и $а = $а + $Ь. Следовательно, оператор 11 = может использоваться для присваивания альтернативного значения переменной. Поскольку 11 выполняет простую логическую проверку (истина или ложь), у него не бывает проблем с неопределенными значениями, даже при использовании ключа -w.
В следующем примере ||= присваивает переменной $starting_point значение "greenwich", если оно не было задано ранее. Предполагается, что $starting_point не принимает значений 0 или "0", а если принимает - то такие значения должны быть заменены:
$starting_point ||= "greenwich";
В операторах присваивания || нельзя заменять оператором оr, поскольку or имеет слишком низкий приоритет. Выражение $а = $b or $с эквивалентно ($а = $b) or $c. В этом случае переменной $Ь всегда присваивается $а, а это совсем не то, чего вы добивались.
Не пытайтесь распространить это любопытное применение || и ||= со скалярных величин на массивы и хэши. У вас ничего не выйдет, потому что левый операнд интерпретируется в скалярном контексте. Приходится делать что-нибудь подобное:
@а = @b unless @a; # Копировать, если массив пуст @а = @b ? @b : @с; # Присвоить @b, если он не пуст, иначе @с
Требуется поменять значения двух скалярных переменных, но вы не хотите использовать временную переменную.
Воспользуйтесь присваиванием по списку:
($VAR1, $VAR2) = ($VAR2, $VAR1);
В большинстве языков программирования перестановка значений двух переменных требует промежуточного присваивания:
$temp = $a; $а = $Ь; $b = $temp;
В Perl дело обстоит иначе. Язык следит за обеими сторонами присваивания и за тем, чтобы ни одно значение не было случайно стерто. Это позволяет избавиться от временных переменных:
$а="alpha"; $b="omega"; ($а, $b) = ($Ь, $а); # Первый становится последним - и наоборот
Подобным способом можно поменять местами сразу несколько переменных:
($alpha, $beta, $production) = qw(January March August); # beta перемещается в alpha, # production - в beta, # alpha - в production ($alpha, $beta, $production) = ($beta, $production, $alpha);
После завершения этого фрагмента значения переменных $alpha, $beta и $production будут равны соответственно "March", "August" и "January".
Требуется вывести код, соответствующий некоторому символу в кодировке ASCII, или наоборот - символ по ASCII-коду.
Воспользуйтесь функцией ord для преобразования символа в число или функцией сhr - для преобразования числа в символ:
$num = ord($char); $char = chr($num);
Формат %с в функциях printf и sprintf также преобразует число в символ:
$char = sprintf ("%с", $num); # Медленнее, чем chr($num) printf("number %d is character %c\n", $num, $num); number 101 is character e
Шаблон С*, используемый в функциях pack и unpack, позволяет быстро преобразовать несколько символов:
@АSCII= unpack("c*". $string); @STRING = pack("С*", $ascii);
В отличие от низкоуровневых, нетипизованных языков вроде ассемблера, Perl не считает эквивалентными символы и числа; эквивалентными считаются строки и числа. Это означает, что вы не можете произвольно присвоить вместо символа его числовое представление, или наоборот. Для преобразования между символами и их числовыми значениями в Perl существуют функции chr и ord, взятые из Pascal:
$ascii_value = ord("e"); # Теперь 101 $character = chr(101); # Теперь "e"
Символ в действительности представляется строкой единичной длины, поэтому его можно просто вывести функцией print или с помощью формата %s функций printf и sprintf. Формат %с заставляет printf или sprintf преобразовать число в символ, однако он не позволяет вывести символ, который уже хранится в символьном формате (то есть в виде строки).
printf("Number %d is character %c\n",101,101);
Функции pack" unpack, chr и ord работают быстрее, чем sprintf. Приведем, пример практического применения pack x unpack:
@ascii_character_numbers = unpack("C*", "sample"); print "@ascii_character_ numbers \n"; 115 97 109 112 108 101 $word=pack("c*",@ascii_character_numbers); $word = pack("c*",115, 97, 109, 112, 108, 101); # То же самое print "$word\n", sample
А вот как превратить HAL в IBM:
$hal = "hal"; @ascii = unpack("c*", $hal); foreach $val (@ascii) { $val++; # Увеличивает каждый ASCII - код на 1 }; $ibm = pack("c*"), @ascii); print "$ibm\n"; # Выводит "IBM"
Функция ord возвращает числа oт 0 до 255. Этот диапазон соответствует типу данных unsigned char языка С.
Назад | Вперед |