Тарифы Услуги Сим-карты

Perl: выражения и операции. Два набора операторов сравнения. Логическое И и логическое ИЛИ

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

Все операции PERLа подразделяются на:

Операции ввода-вывода описаны в статье "Perl: описатели файлов ", операции с регулярными выражениями — "Perl: регулярные выражения ", раздел "Операции с регулярными выражениями".

Операции сравнения

Операции сравнения сравнивают два операнда и возвращают 1 или 0 в зависимости от результата этого сравнения. PERL содержит два набора операций сравнения: для сравнения чисел и для сравнения строк. Операции первой группы сначала преобразуют операнды в числа, а затем их сравнивают. Операции второй группы преобразуют операнды в строки и сравнивают их в лексикографическом порядке . Если задана директива use locale , то сравнение срок производится с учетом национальной настройки.

Сравнение чисел Сравнение строк Название Описание
a < b a lt b Меньше 1, если левый операнд меньше, чем правый операнд.
a > b a gt b Больше 1, если левый операнд больше, чем правый операнд.
a <= b a le b Не больше 1, если левый операнд меньше или равен правому операнду.
a => b a ge b Не меньше 1, если левый операнд больше или равен правому операнду.
a == b a eq b Равно 1, если левый операнд равен правому операнду.
a != b a ne b Не равно 1, если левый операнд не равен правому операнду.
a <=> b a cmp b Сравнение -1, если левый операнд меньше, чем правый; 0, если они равны; 1, если левый операнд больше, чем правый.

Следующий пример

$a = 299;
$b = 30;
if ($a < $b)
{
print "Число $a меньше числа $b\n";
}
if ($a lt $b)
{
print "Строка $a меньше строки $b\n";
}

выведет сообщение: Строка 299 меньше строки 30 .

Логические операции

PERL содержит два набора логических операций , которые идентичны по своему результату, но имеют разный приоритет. Обратите внимание на то, что результаты операций AND и OR отличаются от принятых в других языках программирования.

Операции and , or , xor и not имеют самый низкий приоритет среди всех операций PERLа. Это позволяет использовать их в правой части операторов без дополнительных круглых скобок, например:

Open HANDLE, "file.dat" or die "Error: $!\n";

Использование операции || в этом примере потребует скобок:

Open(HANDLE, "file.dat") || die "Error: $!\n";

Битовые операции

Битовые операции применяются к операндам, представленным как двоичные числа (т. е. как цепочки битов), и возвращают значение, означающее результат операции.

Операция Название Описание
a & b Побитовое AND Возвращает в каждой битовой позиции 1, если соответствующие позиции обоих операндов равны 1.
a | b Побитовое OR Возвращает в каждой битовой позиции 1, если соответствующая позиция хотя бы одного операнда равна 1.
a ^ b Побитовое XOR Возвращает в каждой битовой позиции 1, если соответствующая позиция ровно одного операнда равна 1.
~a Побитовое NOT Унарная операция. Инвертирует каждую битовую позицию операнда.
a << b Сдвиг влево Сдвигает двоичное представление левого операнда влево на количество бит, заданное вторым операндом.
a >> b Cдвиг вправо Сдвигает двоичное представление левого операнда вправо на количество бит, заданное вторым операндом.

Операции сдвига применимы только к числовым операндам, но остальные битовые операции применимы и к числам, и к строкам. Если одним из операндов битовой операции является число, то оба операнда преобразуются в целые числа. Если же оба операнда строки, то они преобразуются в строки одинаковой длины и операция выполняется над каждым битом полученных строк. Это позволяет нам применять битовые операции к операндам любой длины. При этом операции | и ^ дополняют более короткую строку справа нулевыми битами, а операция & обрезает более длинную строку до размера более короткой. Мы можем явно указать тип операции, используя кавычки для строк или 0+ для чисел. Примеры:

Print 1.9 | 2; # 3 (плавающий операнд урезан до целого)
print 150 | "105"; # 255 (0x96 | 0x69 равно 0xFF)
print "150" | "105"; # "155" (в ASCII)
$a = 150;
$b = "105";
print 0+$a | 0+$b; # числовые операнды
print "$a" | "$b"; # строковые операнды

На выполнение битовых операций влияют директивы управления арифметикой. По умолчанию, целые числа считаются беззнаковыми, поэтому операция правого сдвига заполняет старшие биты результата нулями, а операция ~0 возвращает наибольшее положительное целое число. Директива use integer приводит к тому, что целые числа начинают интерпретироваться как числа со знаком. Поэтому в зоне ее действия операция правого сдвига заполняет старшие биты результата знаковым битом числа, а операция ~0 возвращает число -1 .

Унарные операции

Унарный плюс

Унарный плюс (+) возвращает свой операнд. Единственное осмысленное применение этой операции состоит в том, чтобы отделять имя функции от ее аргументов в скобках. Рассмотрим такой пример:

Print (10 + 20) / 10;

Вопреки ожиданиям, этот оператор печатает не число 3, а число 30. Дело в том, что круглые скобки вокруг аргументов функции имеют в PERLе наивысший приоритет, т. е. операция print (10 + 20) выполняется раньше, чем деление на 10. Желаемый результат достигается использованием унарного плюса перед скобками, который понижает их приоритет:

Print +(10 + 20) / 10;

Унарный минус

Унарный минус (-) изменяет знак числового операнда на противоположный. Если же операнд является строкой, то возвращается следующий результат:

  • если строка начинается с символа "+" или "-", то в результате этот символ заменяется на противоположный;
  • в остальных случаях возвращается конкатенация символа "-" и исходной строки.

В частности, конструкции -слово и "-слово" эквивалентны.

Создание ссылки

Инкремент и декремент

Операции ++ и -- называются соответственно операциями инкремента и декремента . Инкремент увеличивает значение числовой переменной на 1. Если она используется как префикс (++a), то возвращает значение операнда после увеличения его на 1. Если же она используется как постфикс (a++), то возвращает значение операнда перед увеличением его на 1. Если операнд инкремента является строковой переменной, соответствующей образцу /^**$/ , то выполняется посимвольный инкремент строки с переносом. Примеры:

Print ++($x = "99"); # "100"
print ++($x = "a0"); # "a1"
print ++($x = "Az"); # "Ba"
print ++($x = "zz"); # "aaa"

Декремент применяется только к числовым переменным и уменьшает значение переменной на 1. Если эта операция используется как префикс (--a), то она возвращает значение операнда после уменьшения его на 1. Если она используется как постфикс (a--), то возвращает значение операнда перед уменьшением его на 1. Примеры:

Print --($x = 99); # 98
print (($x = 99)--); # 99
print --($x = "a0"); # -1

Именованные унарные операции

Аддитивные операции

Существуют две аддитивные операции над числами (сложение и вычитание) и одна над строками (конкатенация).

Print "1" + "2"; # 3
print "1" . "2"; # "12"

Мультипликативные операции

Существуют четыре мультипликативные операции над числами (умножение, деление, остаток по модулю и возведение в степень) и одна над строками (повторение).

Операция Название Описание
a * b Умножение Возвращает произведение двух числовых операндов.
a / b Деление Возвращает частное от деления двух числовых операндов.
a % b Остаток по модулю Возвращает целый остаток от деления левого операнда на правый. Плавающие числа перед операцией округляются до целых. Если b отрицательно, то и результат отрицателен.
a ** b Возведение в степень Возвращает a в степени b .
a x b Повторение Левый операнд должен быть строкой или списком, правый — числом. Возвращает операнд a , повторенный b раз.

Print "-" x 80; # печатает строку минусов
@ones = (1) x 5; # @ones = (1, 1, 1, 1, 1)
@ones = (2) x @ones; # @ones = (2, 2, 2, 2, 2)

Операции присваивания

Операции присваивания присваивают левому операнду результат операции, который определяется правым операндом и самой операцией. Базовая операция присваивания имеет вид a = b , что означает: присвоить переменной a значение операнда b . Все остальные операции присваивания являются сокращениями других операций, совмещенных с присваиванием, как показано в следующей таблице.

Операция Значение
a += b a = a + b
a -= b a = a - b
a .= b a = a . b
a *= b a = a * b
a /= b a = a / b
a %= b a = a % b
a x= b a = a x b
a **= b a = a ** b
a <<= b a = a << b
a >>= b a = a >> b
a &= b a = a & b
a |= b a = a | b
a ^= b a = a ^ b
a &&= b a = a && b
a ||= b a = a || b

Операция присваивания возвращает свой левый операнд и потому может использоваться в левой части следующей операции присваивания. Например

($a += 2) *= 3;

эквивалентно

$a += 2;
$a *= 3;

Присваивание списка списку возвращает список переменных, которым присвоены значения. Присваивание списка скаляру возвращает количество элементов в этом списке.

q-операции

В большинстве языков программирования кавычки служат для образования строковых констант. Однако, в PERLе они являются операциями, обеспечивающими интерполяцию строк и сопоставление с образцом. Такие операции мы будем называть q-операциями (от английского слова quote, т. е. кавычка). PERL содержит два набора q-операций, перечисленных в следующей таблице.

Кавычки q-операция Значение Интерполяция
"" q() Константа Нет
"" qq() Константа Да
`` qx() Команда Да (если ограничители не "")
qw() Список слов Нет
qr() Регулярное выражение Да (если ограничители не "")
// m() Сопоставление с образцом Да (если ограничители не "")
s()() Подстановка Да (если ограничители не "")
tr()() Транслитерация Только escape-последовательностей

Здесь вместо скобок () можно использовать любой символ, не являющийся буквой, цифрой или пробелом, либо парные ограничители: (), , {}, <>. Примеры использования q-конструкций для создания строковых констант были приведены в п. 6.2.3.2 ; об их использовании в регулярных выражениях см. п. 6.4.6 .

Прочие операции

Разадресация

Операция разадресации имеет вид:

Операции связывания

Большинство операций над регулярными выражениями работают со специальной переменной $_ . Для сопоставления с образцом произвольных строк используются операции связывания , которые имеют вид:

A =~ ba !~ b

где a — любое строковое выражение, а b — образец для сопоставления, подстановки или транслитерации. Операция =~ возвращает истину, если сопоставление, подстановка или транслитерация прошли успешно, и ложь в противном случае. Операция!~ возвращает логическое отрицание результата =~ . Примеры использования этих операций см. в п. 6.4.6 .

Задание диапазона

Операция задания диапазона имеет вид:

На самом деле это две разные операции в зависимости от контекста. В контексте списка эта операция возвращает список значений (a a+1 … b) . Для строк диапазон формируется с использованием инкремента , например:

Foreach (1..10)
{
# выполняет цикл 10 раз
}
@a = @a[$#a-4 .. $#a]; # вырезает последние пять элементов
@a = ("abc".."abe"); # @a = ("abc", "abd", "abe")

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

Результат не становится ложным до следующего обращения к этой операции. Операция.. может проверить правый операнд и стать ложной при том же ее вычислении, когда она стала истинной, но один раз она вернет истину. Если мы хотим, чтобы она не вычисляла правый операнд до следующего обращения к ней, то должны использовать форму

В остальном операции.. и... идентичны. Правый операнд не оценивается, пока операция находится в состоянии "ложь", а левый операнд не оценивается, пока операция находится в состоянии "истина". Значение, возвращаемое данной операцией, это пустая строка в ложном состоянии, и последовательные целые числа, начиная с 1, в истинном состоянии. Последовательный номер сбрасывается для нового диапазона. К последнему номеру диапазона добавляется строка "E0". Если какой-либо из операндов является константой, то он неявно сравнивается со специальной переменной $. (содержащей номер текущей строки текущего файла). Следующий пример открывает заданный файл и печатает его строки с первой по пятую.

Open HANDLE, "filename.ext";
while ()
{
print if (1..5);
}

Условная операция

Условная операция — это тернарная операция, которая имеет вид:

Test ? value1: value2

где test , value1 и value2 — любые выражения. Если test истинно, то операция возвращает значение value1 , в противном случае она возвращает значение value2 . Пример:

Printf "У меня %d дру%s.\n", $n, ($n == 1) ? "г" : (($n < 5) ? "га" : "зей");

Эта операция может использоваться в левой части операции присваивания, если и value1 , и value2 являются переменными, например:

($test ? $a: $b) = $c;

Операция запятая

Операция запятая вызывает последовательное вычисление значений двух выражений и возвращает второе из них. Она имеет вид:

Expr1, expr2

где expr1 и expr2 — любые выражения. В списках запятая служит разделителем элементов списка.

PERL содержит синоним этой операции вида

Expr1 => expr2

Такая форма обычно используется для парных элементов списка, например, при инициализации ассоциативных массивов. Кроме того, если левый операнд операции => является словом, то он интерпретируется как строка (см. п. 6.2.7 )

Порядок выполнения операций

При вычислении выражений PERL учитывает приоритет операций : операции, имеющие больший приоритет, выполняются первыми. Для изменения порядка выполнения операций следует пользоваться круглыми скобками: выражение, заключенное в них, имеет наивысший приоритет. В следующей таблице приведен список всех операций языка PERL в порядке убывания их приоритетов; операции, расположенные в одной строке таблицы, имеют равный приоритет и выполняются либо слева направо, либо справа налево, как указано в таблице.

Операция Ассоциативность
термы и списки левая
-> левая
++ -- нет
** правая
! ~ \ + (унарный) - (унарный) правая
=~ !~ левая
* / % x левая
+ - . левая
<< >> левая
именованные унарные операции нет
< > <= >= lt gt le ge нет
== != <=> eq ne cmp нет
& левая
| ^ левая
&& левая
|| левая
.. ... нет
?: правая
= op = правая
, => левая
not правая
and левая
or xor левая

И узнали, как числа и строки конвертируются друг в друга на лету. Мы даже мельком взглянули на условное выражение if , но пока что не узнали, как сравнить два скаляра. Об этом пойдет речь в этой части.

Если у нас есть две переменные $x и $y, можно ли их сравнить? Равны ли 1, 1.0 и 1.00? А как насчет "1.00"? Что больше - "foo" или "bar"?

Два набора операторов сравнения

В Perl существует два набора операторов сравнения. Так же, как с уже изученными нами бинарными операторами сложения (+), конкатенации (.) и повторения (x), здесь тоже оператор определяет, как ведут себя операнды и как они сравниваются.

Вот эти два набора операторов:

Числовое Строковое Значение == eq равно!= ne не равно < lt меньше > gt больше <= le меньше или равно >= ge больше или равно

Операторы слева сравнивают числовые значения, а справа (в средней колонке) сравнивают значения, основываясь на ASCII таблице или на текущей локали.

Рассмотрим несколько примеров:

Use strict; use warnings; use 5.010; if (12.0 == 12) { say "TRUE"; } else { say "FALSE"; }

В этом простейшем случае Perl выведет TRUE, так как оператор == сравнивает два числа, так что Perl"у не важно, записаны ли они как целые числа, или как числа с плавающей точкой.

В следующем сравнении ситуация немного интереснее

"12.0" == 12

это выражение также истинно, ведь оператор Perl"а == конвертирует строку в число.

2 < 3 истинно, так как < сравнивает два числа. 2 lt 3 также истинно, ведь 2 находистя перед 3 в таблице ASCII. 12 > 3 очевидно, истинно. 12 gt 3 вернет FALSE

Возможно, с первого взгляда кому-то это покажется неожиданным, но если подумать, Perl ведь сравнивает строки посимвольно. Так что он сравнивает "1" и "3", и раз они отличаются и "1" стоит перед "3" в таблице ASCII, на этом этапе Perl решает, строковое значение 12 меньше, чем строковое значение 3.

Всегда нужно быть уверенным, что сравниваешь значение именно так, как нужно!

"foo" == "bar" будет истинно

Также это выдаст предупреждение, если(!) предупреждения включены с помощью use warnings . Причина его в том, что мы используем две строки как числа в числовом сравнении ==. Как упоминалось в предыдущей части, Perl смотрит на строку, начиная с левого конца, и конвертирует ее в число, которое там находит. Поскольку обе строки начинаются с букв, они будут конвертированы в 0. 0 == 0, так что выражение истинно.

С другой стороны:

"foo" eq "bar" ложно

Так что всегда нужно быть уверенным, что сравниваешь значение именно так, как нужно!

То же будет при сравнении

"foo" == "" будет истинно

"foo" eq "" будет ложно

Результаты в этой таблице могут пригодиться:

12.0 == 12 ИСТИНА "12.0" == 12 ИСТИНА "12.0" eq 12 ЛОЖЬ 2 < 3 ИСТИНА 2 lt 3 ИСТИНА 12 > 3 ИСТИНА 12 gt 3 ЛОЖЬ! (внимание, может быть неочевидно с первого взгляда) "foo" == "" ИСТИНА! (Выдает предупреждение, если использована прагма "warnings") "foo" eq "" ЛОЖЬ "foo" == "bar" ИСТИНА! (Выдает предупреждение, если использована прагма "warnings") "foo" eq "bar" ЛОЖЬ

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

Use strict; use warnings; use 5.010; print "input: "; my $name = ; chomp $name; if ($name == "") { # неверно! здесь нужно использовать eq вместо == ! say "TRUE"; } else { say "FALSE"; }

Если запустить этот скрипт и ввести "abc", мы получим ответ TRUE, так как perl решил, что "abc" это то же, что и пустая строка.

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

Таблица 4.1. Операции отношения

Операция Числовая Строковая Значение
Равенство == eq Истина, если операнды равны, иначе ложь
Неравенство != ne Истина, если операнды не равны, иначе ложь
Меньше < lt Истина, если левый операнд меньше правого, иначе ложь
Больше > gt Истина, если левый операнд больше правого, иначе ложь
Меньше или равно <= le Истина, если левый операнд больше правого или равен ему, иначе ложь
Больше или равно >= ge Истина, если правый операнд больше левого или равен ему, иначе ложь
Сравнение <=> cmt 0, если операнды равны
1, если левый операнд больше правого
-1, если правый операнд больше левого

Результатом операций отношения (кроме последней сравнения) является Истина, значение 1, или Ложь, пустая строка "".

Замечание
Значение истина в арифметических операциях интерпретируется как число 1, а в строковых как строка "1". Значение ложь в арифметических операциях интерпретируется как число 0, а в строковых как пустая строка " ".

Числовые операции отношения

Числовые операции отношения применяются к числовым данным, причем один или оба операнда могут задаваться строкой, содержащей правильное десятичное число. Если в числовых операциях отношения какой-либо из операндов задан строкой, содержимое которой не представляет правильное десятичное число, то его значение принимается равным о и отображается предупреждение о некорректном использовании операнда в числовой операции отношения (если включен режим отображения предупреждений интерпретатора Perl). Смысл операций отношения для числовых данных соответствует обычным математическим операциям сравнения чисел (пример 4.7).

123 > 89; # Результат: 1 (истина)

123 < 89; # Результат: "" (ложь)

123 <= 89; # Результат: "" (ложь)

89 <= 89; # Результат: 1 (истина)

23 >= 89; # Результат: "" (ложь)

23 <=> 89; # Результат: -1 (правый операнд больше левого)

89 <=> 23; # Результат: 1 (правый операнд больше левого)

Применение числовых операций сравнения не представляет сложности, однако при сравнении на равенство десятичных чисел с плавающей точкой могут проявиться эффекты округления, связанные с ограниченным количеством значащих цифр в мантиссе представления действительных чисел в компьютере и приводящие к "неправильной", с точки зрения пользователя работе операций сравнения. Пример 4.8 иллюстрирует подобную ситуацию.

#! peri -w
$z = 0.7;

$zz = 10+0.7-10; # Переменная $zz содержит число 0.7

# Печать строки "z равно zz", если равны значения переменных $z и $zz print "z равно zz\n" if ($z == $zz);

При попытке выполнить пример 4.8 мы с удивлением обнаружим, что наша программа ничего не напечатает. В чем же дело? Разгадка лежит в операторе вычисления значения переменной $zz. При выполнении арифметических операций в результате ошибок округления получается значение 0.699999999999999 (можете вставить оператор печати переменной $zz и убедиться в этом), хотя и близкое к 0.7, но не равное ему в точности. Следовательно, операция сравнения отработала верно!

Совет
Не используйте операцию сравнения на равенство вещественных чисел, ее результат может не соответствовать ожидаемому с точки зрения математики. Если необходимо проверить равенство двух вещественных чисел, то лучше сравнивать абсолютное значение их разности с некоторым очень маленьким числом (в зависимости от требуемой точности):

abs($a-$b) <= 0.00000001; # Проверка равенства

Строковые операции отношения

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

"A" It "a"; # Результат: истина (код "А" - \101, код "а" - \141)
"a" It "aa";
# с кодом \000, который меньше кода \141
# второго символа "а" строки правого операнда)
"a" It "a "; # Результат: истина (к строке "а" добавляется символ
# с кодом \000, который меньше кода \040
# замыкающего пробела строки правого операнда)
"12" It "9"; # Результат: истина (код "1" - \061, код "9" - \071)
"9" eq 09"; # Результат: ложь (код " " - \040, код "О" - \060)

Обратим внимание на две последние операции сравнения строковых литералов. Содержимое их операндов может быть преобразовано в правильные числа, и поэтому к ним применимы аналогичные числовые операции отношения. Однако их результат будет существенно отличаться от результата выполнения строковых операций отношения. При использовании операции < в предпоследнем выражении результат будет Ложь, а если в последнем выражении применить операцию ==, то результат будет Истина. Об этом всегда следует помнить, так как Perl автоматически преобразует символьные данные в числовые там, где это необходимо.

Есть несколько способов сравнения объектов в Perl. Можно проверить равенство значений используя инфиксный оператор === . Для неизменных (immutable ) объектов (значения которых нельзя изменить, литералов. Например литерал 7 всегда будет 7) это обычное сравнение значений. Например "hello"==="hello" всегда верно потому, что обе строки неизменны и имеют одинаковое значение.

Для изменяемых объектов === сравнивает их идентичность. === возвращает истину, если его аргументы являются псевдонимами одного и того же объекта. Или же двое объектов идентичны, если это один и тот же объект. Даже если оба массива @a и @b содержат одинаковые значения, если их контейнеры разные объекты, они будут иметь различные идентичности и не будут тождественны при сравнении === :

My @a = 1, 2, 3; my @b = 1, 2, 3; say @a === @a; # 1 say @a === @b; # 0 # здесь используется идентичность say 3 === 3; # 1 say "a" === "a"; # 1 my $a = "a"; say $a === "a"; # 1

Оператор eqv возвращает Истина если два объекта одного типа и одинаковой структуры. Так для @a и @b указанных в примере, @a eqv @b истинно потому, что @a и @b содержат одни и те же значения. С другой стороны "2" eqv 2 вернет False , так как аргумент слева строка, а справа - число, и таким образом они разных типов.

Так же как == преобразует свои аргументы в числа, инфиксный оператор eq сравнивает равенство строк, преобразуя аргументы в строки при необходимости.

If $greeting eq "hello" { say "welcome"; }

Другие операторы сравнивают строки лексикографически.

На самом деле более удобная форма для!== , который в свою очередб представляет собой объединеие метаоператора! и инфиксного оператора == . Такое же обяснение приминительно к ne и!eq .

Операторы three-way сравнения получают два операнда и возвращают Order::Increase , если операнд слева меньше, Order::Same - если равны, Order::Decrease - если операнд справа меньше (Order::Increase , Order::Same и Order::Decrease являются перечислениями (enums) ; см.). Для числовых сравнений используется оператор <=> , а для строковых это leg (от англ. l esser, e qual, g reater). Инфиксный оператор cmp также является оператором сравнения, возвращающий три результата сравнения. Его особенность в том, что он зависит от типа аргументов: числа сравнивает как <=> , строки как leg и (например) пары сначала сравнивая ключи, а затем значения (если ключи равны).

Say 10 <=> 5; # +1 say 10 leg 5; # because "1" lt "5" say "ab" leg "a"; # +1, lexicographic comparison

Типичным применением упомянутых three-way операторов сравнения является сортировка. Метод.sort в списках получает блок или функцию, которые сравнивают свои два аргумента и возвращают значения отрицательные если меньше, 0 - если аргументы равны и больше 0, если первый аргумент больше второго. Эти результаты затем используются при сортировке для формирования результата.

Say ~.sort; # output: Concrete abstract say ~.sort: -> $a, $b { uc($a) leg uc($b) }; # output: abstract Concrete

По умолчанию используется сортировка чувствительная к регистру, т.е. символы в верхнем регистре "больше" символов в нижем. В примере используется сортировка без учета регистра.

Разные операторы сравнения приводит свои аргументы к определённым типам перед сравнением их. Это полезно, когда требуется конкретное сравнение, но типы параметров неизвестны. Perl 6 предоставляет особый оператор который позволяет производить сравнение "Делай Как Надо" (Do The Right Thing) с помощью ~~ - оператора "умного" сравнения.

If $pints-drunk ~~ 8 { say "Go home, you"ve had enough!"; } if $country ~~ "Sweden" { say "Meatballs with lingonberries and potato moose, please." } unless $group-size ~~ 2..4 { say "You must have between 2 and 4 people to book this tour."; }

Оператор "умного" сопоставления всегда решает какого рода сравнение производить в зависимости от типа значения в правой части. В предыдущих примерах эти сравнения были числовым, строковым и сравнением диапазонов соответственно. В данной главе была продемонстрирована работа операторов сравнения: чисел - == и строк eq .Однако нет оператора для сравнения диапазонов. Это является частью возможностей "умного" сопоставления: более сложные типы позволяют реализовывать необычные идеи сочетая сравнения их с другими.

"Умное" сопоставление работает, вызывая метод ACCEPTS у правого операнда и передавая ему операнд слева как аргумент. Выражение $answer ~~ 42 сводится к вызову 42.ACCEPTS($answer) . Данная информация пригодится, когда вы прочитаете последующие главы, посвященные классам и методам. Вы тоже напишите вещи, которые смогут производить "умное" сопоставление, реализовав метод ACCEPTS для того, чтобы "работало как надо".

Операторы в Perl-е имеют различный приоритет. Операторы, заимствованные из C , сохранили между собой ту же иерархию, что и в C . Термы имеют самый большой приоритет, они содержат переменные, кавычки, выражения в скобках, функции с их параметрами. Если за списковым оператором (например, print()) или унарным оператором (например, chdir()) следует список аргументов, заключенный в скобки, то эта последовательность имеет самый высокий приоритет, подобно функции с аргументами. Аналогично термам обрабатываются последовательности do{} и eval{} .

3.4.2 Оператор ``стрелка""

Также, как в С и С++ ``- > "" является инфиксным оператором ссылки. Если правая часть является [...] или {...} подпрограммой, тогда левая часть должна быть символьной ссылкой на массив или хэш. Если правая часть - это имя метода или скалярная переменная содержащая имя метода, то левая часть должна быть объектом или именем класса.

П2.3.4.3 Операторы ++ и - -

Эти операторы работают также как и в С. То есть, если они стоят перед переменной, то они увеличивают или уменьшают переменную до возвращения значения. Если они стоят после переменной, то увеличение или уменьшение переменной происходит после возврата значения. Если переменная содержит в себе число или употребляется в скалярном контексте, то использование ++ дает обычное увеличение значения. Если же переменная употреблялась только в строковом контексте, не является пустой строкой и содержит символы a-z,A-Z,0..9 , то происходит строковое увеличение значения переменной:
print ++($foo = "99"); - напечатает 100
print ++($foo = "a0"); - напечатает a1
print ++($foo = "Az"); - напечатает Ba
print ++($foo = "zz"); - напечатает aaa

3.4.4 Экспоненциальный оператор

В Perl-е двойная звездочка ** является экспоненциальным оператором. Он требует к себе даже больше внимания, чем унарный минус: -2**4 это -(2**4) , но не (-2)**4 .

3.4.5 Символьные унарные операторы

Унарный! означает логическое отрицание. Унарный минус, в случае числового значения переменной, обозначает обычное арифметическое отрицание. Если операндом является идентификатор, то возвращается строка, состоящая из знака минус и идентификатора. Если строка начинается со знака + или - , то возвращается строка, начинающаяся с противоположного знака. Унарная тильда `` ~ "" обозначает побитовое отрицание.
Унарный плюс не имеет влияния даже на строки. Он используется для отделения имя функции от выражения заключенного в скобки, которое иначе рассматривается как список аргументов.

Rand (10) * 20; - (rand10) * 20; rand +(10) * 20; - rand(10 * 20); Унарный бэкслэш ``"" обозначает ссылку на то, что стоит за ним.

3.4.6 Операторы связки

Знак равенства с тильдой ``= ~ ""связывает выражение слева с определенным шаблоном. Некоторые операторы обрабатывают и модифицируют переменную $_ . Эти же операции иногда желательно бывает выполнить над другой переменной. Правый аргумент это образец поиска, подстановки или трансляции, левый аргумент - это то, что должно быть подставлено вместо $_ . Возвращаемая величина показывает успех операции. Бинарное ``! ~ "" это тоже самое, что и ``= ~ "", только возвращаемая величина является отрицательной в логическом смысле.

3.4.7 Бинарные операторы

Звездочка * - умножение двух чисел. Cлэш / - деление числа на число. Процент % - вычисляет модуль двух чисел, x - оператор повторения. В скалярном контексте возвращает строку, состоящую из многократно повторенного левого операнда, причем повторяется он то количество раз, которое стоит справа. В списковом контексте он многократно повторяет список. print "a" x 80; напечатает букву a 80 раз.
@ones = (1) x 80; массив из восьмидесяти единиц.
@ones = (5) x @ones сделает все элементы равными пяти.
Бинарный плюс - операция сложения двух чисел.
Бинарный минус - операция вычитания двух чисел.
Бинарная точка - конкатенация строк.

3.4.8 Операторы сдвига

Двоичный сдвиг осуществляется, как и во многих других языках программирования, с помощью операторов ``<<"" и ``>>"". При применении этих операторов значения левых аргументов сдвигаются в соответствующую сторону на количество разрядов, указанное в правых аргументах. Аргументы должны быть целочисленными.

3.4.9 Операторы сравнения

``<"" - возвращает TRUE если левый аргумент численно меньше, чем правый.
``>"" - возвращает TRUE если правый аргумент численно меньше, чем левый.
``<="" - возвращает TRUE если правый аргумент численно меньше или равен левому.
``>="" - возвращает TRUE если левый аргумент численно меньше или равен правому.
``gt"" - возвращает TRUE если левый аргумент меньше (в строковом контексте), чем правый.
``lt"" - возвращает TRUE если правый аргумент меньше (в строковом контексте), чем левый.
На поведение операторов lt и gt влияют установки системного языка, если операционная система способна работать с несколькими языками. По этой причине операторы должны корректно работать со строками на языках, отличных от US ASCII , что в системе UNIX задается указанием свойств LC_COLLATE системного locale .

3.4.10 Операторы эквивалентности

Возвращает TRUE , если левый аргумент численно эквивалентен правому.
!= возвращает TRUE , если левый аргумент численно неэквивалентен правому.
<=> возвращает -1, 0 или 1 в зависимости от того, численно меньше, равен или больше левый аргумент правого.
eq возвращает TRUE , если левый аргумент эквивалентен правому (в строковом контексте).
ne возвращает TRUE , если левый аргумент неэквивалентен правому (в строковом контексте).
cmp возвращает -1, 0 или 1 в зависимости от того, меньше равен или больше левый аргумент правого (в строковом контексте).

3.4.11 Побитовое И, побитовое ИЛИ и Исключающее ИЛИ

Бинарное & возвращает объединенные побитово операнды.
Бинарное | возвращает перемноженные побитово операнды.
Бинарное ^ возвращает исключенные побитово операнды.

3.4.12 Логическое И и логическое ИЛИ

Бинарное && - логическое И. Если левый аргумент FALSE , то правый не проверяется.
Бинарное || - логическое ИЛИ. Если левый аргумент TRUE , то правый аргумент не проверяется.
||""и && отличаются от подобных операторов в \verb C| тем, что вместо 0 или 1 они возвращают последнюю обработанную величину. Таким образом, наиболее удобным способом определить домашний каталог пользователя из переменной окружения HOME будет (на практике такой способ определения домашнего каталога пользователя не рекомендуется):

$home = $ENV{"HOME"} || $ENV{"LOGDIR"} || (getpwuid($<)) || die "You"re homeless!\n"; В качестве более удобной для чтения альтернативы Perl поддерживает операторы and и or , которые будут описаны далее. Их приоритет ниже, однако их можно с удобством использовать, не расставляя скобки, после операторов, аргументами которых являются списки: unlink "alpha", "beta", "gamma" or gripe(), next LINE; Если писать в стиле C , то это может быть записано так: unlink("alpha", "beta", "gamma") || (gripe(), next LINE);

3.4.13 Оператор диапазона

Оператор диапазона. Реально это два разных оператора, в зависимости от контекста. В списковом контексте он работает как оператор диапазона от левого аргумента до правого.

For (1..10) { #code } В скалярном контексте он возвращает булевское значение. Если левый операнд TRUE , то.. принимает значение TRUE , если правый операнд тоже TRUE . if (101..200) { print "hi;)";} - напечатает вторую сотню строк

3.4.14 Условный оператор

?: также как и в C является условным оператором. Он работает подобно if-then-else . Если аргумент перед? - TRUE , то возвращается аргумент перед: , в противоположном случае возвращается аргумент после: . Скалярный или списковый контекст второго и третьего аргументов передается по наследству.

($a_or_b ? $a: $b) = $c;

3.4.15 Операторы присваивания

Обычный оператор присваивания. Вообще операторы присваивания работают также как и в C . $a += 2; - то же самое, что и $a = $a + 2; Можно использовать следующие сокращения:

**= += *= &= <<= &&= -= /= |= >>= ||= .= %= ^= x= ($a += 2) *= 3; - то же самое, что и: $a = $a + 2; $a = $a * 3;

3.4.16 Оператор ``запятая""

Оператор запятая или comma-оператор. В скалярном контексте он обрабатывает левый аргумент и отбрасывает его значение, потом обрабатывает правый аргумент и возвращает его величину. В этом он подобен comma-оператору из C . В списковом контексте он играет роль разделителя аргументов и вставляет оба аргумента в список. => является синонимом comma-оператора.

3.4.17 Логическое НЕ

Унарное NOT возвращает отрицание аргумента. Оно эквивалентно! , за исключением более низкого приоритета.

П2.3.4.18 Логическое И, ИЛИ и Исключающее ИЛИ

and возвращает конъюнкцию двух выражений. Он эквивалентен && , за исключением более низкого приоритета. or возвращает дизъюнкцию аргументов. Он эквивалентен ||, за исключением более низкого приоритета. xor (eXclusive OR) - исключающее ИЛИ, возвращает истину, если истинен ровно один из аргументов.

3.4.19 Оператор чтения из файла

В Perl есть несколько операций ввода-вывода. Для вывода из файла используется команда <>.

Open(STDIN,"/etc/passwd"); while ($string = ) { @a = split(/[:]/,$string); } Внутри этих скобок стоит дескриптор файла. Считывание происходит построчно. В конце файла принимает значение FALSE и цикл while завершается. По умолчанию считывание происходит в переменную $_ . Нулевой дескриптор файла используется также как в sed и awk , то есть считывается поток из файлов перечисленных в командной строке.

3.4.20 Оператор замены строки

Оператор s/PATTERN/REPLACEMENT/egimosx производит поиск строки, соответствующей шаблону PATTERN и если строка найдена, то подстановку на ее место текста REPLACEMENT . Возвращает количество произведенных подстановок. Если перед этим не использовался оператор =~ или!~ для определения переменной, которая будет обрабатываться, то будет модифицироваться переменная $_ . Этот оператор используется со следующими опциями: e интерпретирует правую часть как выражение. g производит подстановку на место каждой строки, соответствующей шаблону. i производит поиск различающий большие и маленькие буквы. m обрабатывает строку, как состоящую из нескольких строк. o происходит подстановка только на место первой встреченной строки. s обрабатывает строку, как состоящую только из одной строки. x использует расширенные регулярные выражения. Например:

$path =~ s|/usr/local/bin|/usr/bin|; ($foo = $bar) =~ s/this/that/o; $count = ($paragraf =~ s/Mister\b/Mr./gm);

3.4.21 Оператор замены множества символов

tr/SEARCHLIST/REPLACEMENTLIST/cds y/SEARCHLIST/REPLACEMENTLIST/cds Заменяет все найденные символы из множества символов SEARCHLIST на соответствующие символы из множества символов REPLACEMENTLIST . Возвращает число символов, которые были заменены или удалены. Если посредством операторов =~, !~ не была указана никакая строка, то обрабатывается переменная $_ . y является синонимом tr . Если SEARCHLIST заключен в скобки, то REPLACEMENTLIST тоже заключается в скобки, которые могут отличаться от тех, в которые заключается шаблон, например:

Tr tr(+-*/)/ABCD/ Этот оператор употребляется со следующими опциями: c заменяет символы, которые не входят во множество SEARCHLIST на REPLACEMENTLIST , например: tr/a-zA-Z/ /cs; заменит неалфавитные символы. d Стирает символы, которые ни на что не заменяются. s Переводит последовательность символов, которые заменяются на один и тот же символ в один символ. Например: $a = "CCCCCCCCC"; $a =~ tr/C/D/s; теперь $a = "D"