Глава 6.3. Выражения и операции

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

Операции ввода-вывода описаны в п. 6.2.11, операции с регулярными выражениями — в п. 6.4.6.

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

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

Таблица 6.1. Операции сравнения
Сравнение чисел Сравнение строк Название Описание
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.

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

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

Таблица 6.2. Логические операции
Операция Название Описание
a && b a and b Логическое AND Если первый операнд ложен, то 0, иначе значение второго операнда.
a || b a or b Логическое OR Если первый операнд истинен, то его значение, иначе значение второго операнда.
  a xor b Логическое XOR 1, если истинен ровно один операнд, иначе 0.
!a not a Логическое NOT Унарная операция. 1, если операнд ложен, иначе 0.

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

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

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

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

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

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

Таблица 6.3. Битовые операции
Операция Название Описание
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.

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

6.3.4.1. Унарный плюс

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

print (10 + 20) / 10;

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

print +(10 + 20) / 10;

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

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

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

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

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

Операция \ возвращает ссылку на операнд. Подробно она рассмотрена в п. 6.2.8.

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

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

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

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

PERL содержит множество именованных унарных операций, которые рассматриваются как функции с одним аргументом, заключенным в необязательные круглые скобки. Например, выражение rand 10 эквивалентно выражению rand(10) и трактуется как вызов функции rand c аргументом 10. Встроенные функции PERLа подробно описаны в гл. 6.9.

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

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

Таблица 6.4. Аддитивные операции
Операция Название Описание
a + b Сложение Возвращает сумму двух числовых операндов.
a - b Вычитание Возвращает разность двух числовых операндов.
a . b Конкатенация Возвращает конкатенацию двух строковых операндов.

Примеры:

print '1' + '2';  # 3
print '1' . '2';  # '12'

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

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

Таблица 6.5. Мультипликативные операции
Операция Название Описание
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)

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

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

Таблица 6.6. Операции присваивания
Операция Значение
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;

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

6.3.8. q-операции

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

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

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

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

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

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

a -> b

Она обеспечивает доступ к содержимому ссылок и подробно рассмотрена в п. 6.2.8.

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

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

a =~ b
a !~ b

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

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

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

a .. b

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

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

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

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

a ... b

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

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

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

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

test ? value1 : value2

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

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

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

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

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

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

expr1, expr2

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

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

expr1 => expr2

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

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

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

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