Перейти к содержанию

Некоторые сведения о Perl 5/Операции и выражения

Материал из Викиучебника — открытых книг для открытого мира
← Типы данных Глава Операторы →
Операции и выражения


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

Большинство операций работает с двумя операндами, которые записываются по обе стороны от знака операции (бинарная операция). Например в операции сложения операндами выступают слагаемые. Для других операций может требоваться один операнд (унарная операция) или три (тернарная операция). В некоторых операциях какие-то операнды можно опускать.

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

Арифметические операции

[править]
Операция Пример Описание Операция Пример Описание
Арифметические операции
+
6.35+8.31
Сложение. Выполняет арифметическое сложение
-
9.15-5
Вычитание. Выполняет арифметическое вычитание
*
2*2
Умножение
/
15/3
Деление
**
4**2
Возведение в степень
%
10%5
Остаток от деления
Унарные арифметические операции
+
+5
Унарный плюс
-
-6
Унарный минус. Делает положительное число отрицательным, а отрицательное — положительным
Инкремент/декремент
++
$i = 5, $j=$i++;
Постфиксный инкремент. Увеличивает значение переменной на единицу после всех прочих операций над переменной. В примере значение в $j будет 5, а в $i значение будет 6, потому что инкремент выполняется после присваивания
++
$i = 5, $j=++$i;
Префиксный инкремент. В отличие от постфиксного инкремента, значение в операнде будет увеличено до всех прочих операций над ним. В данном примере в обеих переменных будет 6
--
$i = 5, $j=$i--;
Постфиксный декремент. Уменьшает значение переменной на единицу после всех прочих операций над переменной. В примере значение в $j будет 5, а в $i значение будет 4, потому что декремент выполняется после присваивания
--
$i = 5, $j=--$i;
Префиксный декремент. В отличие от постфиксного декремента, значение в операнде будет уменьшено до всех прочих операций над ним. В данном примере в обеих переменных будет 4
  • В основном арифметические операции направлены на работу с числами, однако операндами могут выступать и строки, причем не обязательно, чтобы они конвертировались в числа. В таких случаях интерпретатор сначала попытается выделить число из символов, начиная с первого. Если выделить число не получается, то результатом конвертации будет 0. Так, строка 5gh4 будет конвертирована в 5, а g130 — в 0.
  • Если в операции остаток от деления (%) второй операнд является вещественным числом и имеет дробную часть, то он предварительно преобразуется в целое число путем простого отброса дробной части.
  • Отрицательное число нельзя возводить не в целую степень. Интерпретатор не будет выдавать никакой ошибки, но при этом результат всегда будет 0.
  • Бинарные арифметические операции выполняются в скалярном контексте. Это означает, что интерпретатор будет ожидать в операндах скалярные переменные. Если в операндах будут массивы, то они будут преобразованы к числу элементов в массиве, а в случае хеш-массива — к числу использованных хеш-записей в нем.
  • Инкремент и декремент можно применять к строковым данным. В случае инкремента, если строка состоит только из латинских букв, то результатом будет новая строка, в которой последняя буква будет заменена на следующую по порядку в алфавите, причем строчная буква заменяется строчной, а прописная — прописной. Аналогично происходит, если строка завершается цифрой. Для декремента Perl будет пытаться конвертировать строку в число по обычным правилам, описанным выше.

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

[править]
Операция Пример Описание Операция Пример Описание
Строковые операции
.
"a"."b"
Конкатенация строк. Объединяет две строки в одну
x
"a" x 3
Повторитель. Повторяет строку в левом операнде N число раз и возвращает из этого строку
  • Строковые операции обычно направлены на строковый тип данных, однако можно использовать и числа. В этом случае числа будут преобразованы в строки.
  • Оператор конкатенации не вставляет пробелы между строками. Обычно для объединения с пробелами прибегают к функции join.
  • Для операции повторения левый операнд всегда приводится к строковому значению. Правым операндом должно быть целое число, либо строка, которая может быть приведена к целому числу. В случае вещественного числа, дробная часть будет просто отбрасываться.
  • Для операции повторения левым операндом может быть список слов, заключенный в круглые скобки, т.е. эта операция может работать в списковом контексте. В таком случае список будет повторен указанное число раз. Такой прием используется для порождения списка, передаваемого конструктору массива.
  • Знак операции повторения следует всегда отделять хотя бы одним пробелом от его операндов, так как в некоторых ситуациях интерпретатор может принять его за часть имени переменной.

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

[править]

Операции отношения

[править]
Операция Пример Описание Операция Пример Описание
Числовые отношения
>
2>1
Больше. Возвращает 1, если ИСТИНА и "", если ЛОЖЬ
>=
3>=1
Больше либо равно. Возвращает 1, если ИСТИНА и "", если ЛОЖЬ
<
-3<0
Меньше. Возвращает 1, если ИСТИНА и "", если ЛОЖЬ
<=
0<=3
Меньше либо равно. Возвращает 1, если ИСТИНА и "", если ЛОЖЬ
==
3==3
Равно. Возвращает 1, если ИСТИНА и "", если ЛОЖЬ
!=
1!=2
Не равно. Возвращает 1, если ИСТИНА и "", если ЛОЖЬ
<=>
15<=>63
Один из операндов больше другого. Возвращает -1, если правый операнд больше левого; 1 — правый операнд меньше левого; 0 — операнды равны
Строковые отношения
eq
"a" eq "a"
Строки лексикографически равны. Возвращает "1", если ИСТИНА и "", если ЛОЖЬ
ne
"a" ne "b"
Строки лексикографически не равны. Возвращает "1", если ИСТИНА и "", если ЛОЖЬ
lt
"a" lt "c"
Левая строка лексикографически меньше правой. Возвращает "1", если ИСТИНА и "", если ЛОЖЬ
le
"a" le "c"
Левая строка лексикографически меньше или равна правой. Возвращает "1", если ИСТИНА и "", если ЛОЖЬ
gt
"d" gt "e"
Левая строка лексикографически больше правой. Возвращает "1", если ИСТИНА и "", если ЛОЖЬ
ge
"d" ge "e"
Левая строка лексикографически больше или равна правой. Возвращает "1", если ИСТИНА и "", если ЛОЖЬ
cmp
"a" cmp "b"
Лексикографически один из операндов не равен другому. Возвращает -1, если правый операнд лексикографически больше левого; 1 — правый операнд лексикографически меньше левого; 0 — операнды лексикографически равны
  • Обратите внимание, что операции отношения скопированы с командной оболочки Bourne Shell, но там все было наоборот: eq, ne, lt, le, gt и ge применялись к числам, а привычные нам знаки использовались для лексикографического сравнивания. Об этом нужно помнить, когда вы переключаетесь с программирования для командной оболочки на программирование для Perl.
  • Лексикографическое сравнивание означает, что сравниваются ASCII кодировки символов. Так символ a лексикографически будет меньше символа b, потому что код последнего (98) больше первого (97). При лексикографическом сравнивании строк учитывается код каждого символа в строке, а также длина строк.
  • ИСТИНА для числовых отношений это число 1, а для строковых — строка "1".
  • В общем случае следует быть осторожным при сравнивании вещественных чисел с целыми, так как тут вступает фактор округления чисел. Следует отметить, что вещественные числа вообще нельзя сравнивать на равенство, так как результат практически всегда будет неправильным. В этом случае следует сравнивать разницу двух вещественных чисел с очень малым числом (погрешностью).

Булевы выражения

[править]
Операция Пример Описание Операция Пример Описание
Булевы операции
&&
1 && 1
Конъюнкция
||
0 || 1
Дизъюнкция
!
! 0
Логическое отрицание
xor
1 xor 1
Исключающее ИЛИ
and
1 and 1
Конъюнкция. Синоним
or
0 or 1
Дизъюнкция. Синоним
not
not 1
Логическое отрицание. Синоним
  • Операции or, and, not и xor появились в Perl, начиная с версии 5.001. Отличие их от аналогичных операций в виде символов в том, что они имеют меньший приоритет при вычислении в сложных выражениях. Такой пониженный приоритет иногда требуется в выражениях по типу $num != 0 or print "\$num == 0";
  • Для булевых операций ИСТИНОЙ признается любое скалярное значение не равное 0, "0" и "", в противном случае это ЛОЖЬ.
  • Булевы операции конъюнкции и дизъюнкции вычисляются по укороченной схеме. Это означает, например, что если при конъюнкции ЛОЖЬ в некотором операнде встречается раньше, чем закончилось выражение, вычисление прекращается на этом операнде с общим результатом ЛОЖЬ.

Побитовые операции

[править]
Операция Пример Описание Операция Пример Описание
Побитовые операции
&
3 & 2
Побитовое И. Выполняет конъюнкцию двух чисел побитово
|
3 | 2
Побитовое ИЛИ. Выполняет дизъюнкцию двух чисел побитово
^
3 ^ 3
Побитовое исключающее ИЛИ
~
~0
Побитовое отрицание
<<
1 << 1
Побитовый сдвиг влево
>>
2 >> 1
Побитовый сдвиг вправо
  • Побитовые операции работают только с числами, если хотя бы один операнд является числом (соответственно другой будет сконвертирован в число). Если оба операнда являются строками, то побитово выполняются операции с кодом каждого символа, даже если строки записаны только цифрами. Если при этом строки разной длины, то меньшая из них дополняется символами \000 до равенства.
  • Все вещественные числа преобразуются к целым.
  • Допустимо использовать любой формат представления чисел: десятичный, шестнадцатеричный и восьмеричный. Язык Perl представляет числа с длиной 32 бит для поразрядных операций, независимо от архитектуры компьютера.

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

[править]
Операция Пример Описание Операция Пример Описание
Операции присваивания
=
$i = 2
Простое присваивание
**=
$i **= 2
Возведение в степень с присваиванием
+=
$i += 2
Сложение с присваиванием
-=
$i -= 2
Вычитание с присваиванием
.=
$i .= 2
Конкатенация с присваиванием
*=
$i *= 2
Умножение с присваиванием
/=
$i /= 2
Деление с присваиванием
%=
$i %= 2
Остаток от деления с присваиванием
x=
$i x= 2
Повторение с присваиванием
&=
$i &= 2
Поразрядное И с присваиванием
|=
$i |= 2
Поразрядное ИЛИ с присваиванием
^=
$i ^= 2
Поразрядное исключающее ИЛИ с присваиванием
<<=
$i <<= 2
Поразрядный сдвиг влево с присваиванием
>>=
$i >>= 2
Поразрядный сдвиг вправо с присваиванием
&&=
$i &&= 2
Конъюнкция с присваиванием
||=
$i ||= 2
Дизъюнкция с присваиванием
  • Простое присваивание является бинарной операцией, правый операнд которой является выражением, а левый — определяет участок памяти (в форме переменной), в который запишется результат выражения. Операция присваивания возвращает левый операнд как результат выражения. По этой причине следующая запись будет синтаксически правильной
    ($i = $j) = 5;
    # Если развернуть эту конструкцию, то получается
    $i = $j;
    $i = 5;  # Так как выражение в скобках вернет $i
    
  • Как в языке Си, в Perl есть составное присваивание, совмещающее в себе операцию и присваивание. Операции с присваиванием также возвращают левый операнд, как результат выражения
    $b = 1;
    $a = ($b += 3);          # Аналогично $a = $b = 4
    $a += ($b += 3);         # Аналогично $a = $a + $b + 3
    (($a += 2) **= 2 ) -= 1; # Аналогично $a = ($a + 2) ** 2 - 1
    
    Обратим внимание, что в большинстве ситуаций в сложных выражениях ставить скобки для операций присваивания обязательно, потому что, как вы узнаете ниже, они парсятся интерпретатором справа налево.

Списковые операции

[править]

Списковая операция — это операция над списком значений. Операции, которым передаются списки и кажущиеся функциями, на самом деле являются списковыми операциями, например print. Это связано с тем, что списковые операции разрешают помещать свои аргументы в скобки. Так, следующие вызовы равнозначны

print $a, "hello", $b;
print ($a, "hello", $b);

Подробнее о списковых операциях будет в главе, посвященной функциям.

Операции заключения в кавычки

[править]

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

Операция Эквивалент Описание Операция Эквивалент Описание
Операции заключения в кавычки
q{}
''
Строковый литерал. Подстановки невозможны
qq{}
""
Строковый литерал
qx{}
``
Команда системы
qw{}
()
Список слов. Подстановки невозможны
m{}
//
Поиск по регулярному выражению
qr{}
perldoc perlrun
//
Шаблон регулярного выражения
s{}{}
s///
Подстановка
tr{}{}
y///
Транслитерация. Подстановки невозможны
  • Фигурные скобки в данных операциях представляют собой разделитель. Они могут быть в любой момент заменены на другой символ или любую другую пару скобок, например
    q{hello}
    q/hello/
    q!hello!
    q<\<hello\>>  # Если символы разделителя есть в значении, то они должны экранироваться.
    
    Внутри разделителей разрешается любое число пробелов, а также внутри большинства операций разрешены подстановки, кроме некоторых (указанных в таблице отдельно).
  • Операция qw{} позволяет вернуть список слов. Чаще всего она используется, чтобы инициализировать массив.
    @arr = qw{ one two three };
    # Это аналогично
    @arr = ("one", "two", "three");
    # и
    $arr[0] = "one";
    $arr[1] = "two";
    $arr[2] = "three";
    
    Обратите внимание, что внутри qw{} запятые ставить не нужно: разделителями являются пробелы.
  • Об остальных операциях будет рассказано далее по ходу изложения.

Операция Here-docs

[править]

В Perl перекочевала Here-docs операция, придуманная для командной оболочки Bourne Shell, которая позволяет инициализировать переменные многострочными строками, либо передавать их на вход некоторой операции, записывая строки прямо в исходном файле программы. Как и в Bourne Shell она записывается так

$str = <<EOF;
строка 1
строка 2
строка 3
EOF

print <<END;
Hello, World!
END

Здесь после знака << вводится так называемое стоп-слово. Далее записывается многострочная строка. Интерпретатор будет искать стоп-слово, для того чтобы понять где заканчивается эта строка. Стоп-слово может быть любым строковым литералом. В наших примерах стоп-словами были EOF и END.

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

$var = "Hello";

print <<END;
\t$var, World!
END

# Аналогично предыдущему вызову
print <<"END";
\t$var, World!
END

# С одинарными кавычками переменные перестанут подставляться и
# не будут работать управляющие последовательности
print <<'END';
\t$var, World!
END

Можно также использовать наклонные кавычки, тогда в Here-docs можно писать процедуры командной оболочки и инициализировать переменные результатом работы этих процедур. Каждая строка в таких процедурах это отдельный ввод команды в оболочку. Следует помнить, что результаты могут зависеть от операционной системы, в которой исполняется Perl.

# Выведет каталоги корневой точки монтирования в *nix системе.
print <<`END`;
ls -l /
END

Если стоп-слово вводится без кавычек, то нельзя ставить пробелы между << и стоп-словом. Если такое случится, то Perl не распознает такого слова и будет захватывать строки до первой пустой строки в исходном файле.

В одном операторе можно ввести больше одного стоп-слова (когда это удобно), если записать их подряд следующим образом.

print <<"END1".<<'END2';
double quotes
END1
single quotes
END2

Другие операции

[править]

Диапазон

[править]

Бинарная операция диапазон .. по-разному интерпретируется в скалярном и списковом контекстах.

В списковом контексте операция возвращает список из чисел, начиная с левого операнда и до последнего с шагом 1, если оба операнда являются числами, либо строки, которые будут сгенерированы в лексикографическом порядке. Если операндами являются числа, то левый операнд всегда должен быть меньше правого, иначе операция вернет пустой список. Числа также должны быть всегда целыми (если это не так, то дробная часть будет просто отбрасываться).

Если строка-левый операнд в лексикографическом смысле больше правого, то результат может зависеть от версии интерпретатора perl: в старых версиях по умолчанию просто возвращается левый операнд; в версии 5.32 будет возвращен ряд, начиная с большего операнда и до символа z. Кроме того, нельзя использовать символы из других алфавитов, кроме латинского: для других алфавитов всегда возвращается левый операнд как результат.

(1..5); # 1 2 3 4 5
(-3..5); # -3 -2 -1 0 1 2 3 4 5
("a".."d"); # a b c d
("01".."10"); # 01 02 03 04 05 06 07 08 09 10
("a1".."b2"); # a1 a2 a3 ... a9 b1 b2

В скалярном контексте диапазон возвращает булево значение и эмулирует поведение операции запятая , из редакторов Sed и AWK (например, конструкция 1,3p). Алгоритм поведения может показаться сложным при первом прочтении, тем не менее следует познакомиться с ним:

  • Диапазон в скалярном контексте всегда находится в одном из двух состояний, которое может измениться при повторном вычислении. Условно мы назовем их ИСТИНА и ЛОЖЬ.
  • Диапазон остается в ЛОЖНОМ состоянии до тех пор, пока ЛОЖНЫМ остается значение левого операнда. Как только он становится ИСТИНОЙ, диапазон переключает состояние в ИСТИНУ и остается в нем, пока правый операнд остается ИСТИННЫМ.
  • Если диапазон находился в состоянии ИСТИНА и правый операнд стал ЛОЖНЫМ, то диапазон снова переключается в ЛОЖНОЕ состояние и вся предыдущая логика повторяется заново.
  • В ЛОЖНОМ состоянии этот диапазон возвращает пустую строку (или ЛОЖЬ). В состоянии ИСТИНА при каждом повторном вычислении возвращается порядковый номер, начиная с 1.
  • В момент перехода из ИСТИНЫ в ЛОЖЬ диапазон возвращает строку, в которой к последнему порядковому номеру добавляется "E0", например 2E0. В ИСТИННОМ состоянии E0 будет отбрасываться.

Вот собственно и весь алгоритм. Добавление "E0" при смене состояния эмулирует поведение именно утилиты AWK. В Sed добавление этой строки происходит только на следующем вычислении. Чтобы эмулировать именно поведение Sed, нужно использовать три точки ....

Диапазоны в скалярном контексте в Perl обычно используются при чтении файлов.

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

[править]

Операция запятая , является бинарной и ведет себя по-разному в скалярном и списковом контекстах:

  • в списковом контексте она является разделителем для элементов в списке;
  • в скалярном контексте она сначала вычисляет левый операнд, потом правый и возвращает результат правого операнда как общий результат.
# Так как левый операнд присваивания это переменная на массив, то выражение исполняется в списковом контексте.
# В этом примере запятая разделяет элементы списка, который передается конструктору массива.
@arr = (1, 2);

# Теперь выражение выполняется в скалярном контексте. Оба операнда для запятой являются простыми числами, но
# как результат операции, будет возвращена 2, которая будет присвоена скаляру.
$scalar = (1, 2);

У запятой есть синоним в виде =>, который мы ранее использовали для построения хеш-массивов в конструкторе. В основном этот знак повторяет запятую, но требует чтобы левый операнд всегда имел строковый тип и корректно в него конвертировался.

Тернарная операция

[править]

В Perl есть тернарная условная операция, которая есть во многих языках программирования. Она записывается точно также как в Си:

<операнд 1> ? <операнд 2> : <операнд 3>

Операция работает так. Если <операнд 1> является ИСТИНОЙ, то возвращается <операнд 2> как результат тернарной операции, иначе возвращается <операнд 3>. Результат тернарной операции можно использовать как в левосторонних (lvalue), так и в правосторонних выражениях (rvalue), главное чтобы они подставлялись в правильном семантическом контексте.

$var = ($num % 3) ? ($var1 += 1) : ($var1 += 2);
(($a % 3) ? ($a += 2) : $a) -= 2;  # Пример с lvalue выражением

Ссылочные операции

[править]

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

Чтобы получить адрес переменной, нужно перед ее именем написать обратный слеш \ (это аналогично операции получения адреса & в языке Си).

# Ссылка на скаляр
$var = 5;
$ptr = \$var;  # Теперь здесь хранится адрес $var

# Ссылка на массив
@arr = (1,2,3);
$aptr = \@arr;

# Ссылка на хеш-массив
%hash = (name => "Larry", surname => "Wall");
$hptr = \%hash;

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

SCALAR(0x800075938)
ARRAY(0x8000759b0)
HASH(0x800075aa0)

Обратите внимание, что в ссылке хранится информация о типе объекта, на который она ссылается и шестнадцатеричный адрес в памяти компьютера.

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

# Разыменовываем ссылку на хеш-массив, чтобы передать его функции keys, которая извлечет из него ключи
@keys = keys(%$hptr);

print $$ptr, "\n";  # Разыменовываем указатель на скаляр

В предыдущем примере с хеш-массивом мы сначала разыменовали ссылку на хеш-массив, указав символ % в начале, а только потом работали с массивом как обычно, передав его функции keys. Perl позволяет также обращаться к данным массивов непосредственно из ссылки (когда это удобно) при помощи операции разыменовывания массивов ->.

print $aptr->[0], $hptr->{name}, "\n";

Подробнее ссылки мы рассмотрим в отдельной главе (см. Ссылки).

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

[править]

Регулярные выражения являются визитной карточкой Perl, который снабжен различными операциями для проверки по ним. Сюда входят поиск (m//), подстановка (s///) и замена (tr///). По умолчанию они работают с переменной $_.

Кроме них есть операции связывания =~ и !~, которые выражают соответственно совпадает с шаблоном и не совпадает с шаблоном.

Регулярные выражения являются очень обширной темой в Perl, поэтому они будут рассмотрены в отдельной главе (см. Работа со строками и регулярные выражения).

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

[править]

В Perl есть большое число функций с одним аргументом, которые с точки зрения синтаксического анализатора являются унарными именованными операциями. О том, является ли функция такой операцией, можно узнать из документации. К таким операциям относятся например do, eval, return, goto, sin, sqrt и другие, а также все операции проверок файлов типа -e (файл существует), -w (в файл можно писать) и другие. Такие операции не требуют скобок вокруг своего аргумента.

По ходу изложения мы затронем многие из этих операций.

Операции ввода/вывода

[править]

Это операции, которые направлены на вывод результатов в файлы или ввод данных в программу из них. Так, унарную именованную операцию print можно рассматривать как операцию вывода.

Чтобы обеспечить ввод данных в программу из файлов, нужно сначала их открыть и получить специальный программный объект, называемый дескриптором файла. Дескриптор файла может быть получен через операцию в виде угловых скобок <дескриптор_файла>:

open(DFILE, "net.cfg"); # Открываем файл. Идентификатор дескриптора DFILE может быть произвольным
@content = <DFILE>; # Читаем файл в массив

Если бы мы открыли файл на запись, то мы можем перенаправить запись в него так

print MYFILE "Hello";

Тема ввода/вывода является очень обширной, поэтому она будет рассмотрена в отдельной главе (см. Ввод и вывод).

Выражения

[править]

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

Синтаксический анализатор Perl, во время разбора выражения, пытается выделить в нем элементарные члены — термы, а потом соединить их знаками операций, причем он выстраивает операции в некотором порядке, учитывая приоритет.

В Perl термами являются литералы, переменные, выражения в скобках, закавыченная строка символов, а также функции с параметрами в скобках. Только терм может быть операндом. Отметим, что в Perl отсутствуют истинные функции: по существу они являются списковыми, унарными именованными операциями, ведущими себя как функции. Вызывая функцию, мы выполняем списковую или унарную операцию, которая возвращает некоторый результат.

# Следующее выражение демонстрирует списковую операцию. В ней сначала
# вычисляется как терм каждый элемент списка, а затем каждый элемент выводится
# на печать списковой операции.
print 2 + 2 * 25 / 4, ' ', 16;   # Напечатает '14.5 16'
# Следующее выражение дает аналогичный результат. Избыточные скобки
# порождают массив, передаваемый операции.
print (2 + 2 * 25 / 4, ' ', 16);   # Напечатает '14.5 16'

# Теперь попробуем добавить конкатенацию:
print (2 + 2 * 25 / 4, ' ', 16) . '$'; # Напечатает '14.5 16'
# Обратите внимание, что результат конкатенации потерялся (нет символа '$'
# в выводе). Это произошло потому, что левый операнд конкатенации, как терм
# по приоритету вычисляется первым, т.е. print выводит результат своего терма
# в аргументе, а не результат конкатенации.

# Допустимо
print print (2 + 2 * 25 / 4, ' ', 16) . '$'; # Напечатает '14.5 161$'
# Появление единицы объясняется тем, что внутренний print вернул код 1, который
# был преобразован в строку и был объединен конкатенацией
# c '$'. Так как между внутренним и внешним print нет переноса
# строки, получилась такая склеенная строка.

При синтаксическом разборе выражений и операторов, как термы рассматриваются конструкции do{} и eval{}, вызовы подпрограмм и методов объектов, анонимные конструкторы массивов скаляров и хешей, а также все операции ввода/вывода.

Еще один немаловажный термин это контекст операции. Операции и термы вычисляются в некотором контексте, от которого зависит поведение операции и возвращаемое ей значение. Существует два основных контекста: скалярный и списковый. Контекст определяет обычно тип данных левого операнда. Так, если он является скаляром, то операция выполняется в скалярном контексте; если массив скаляров — списковом контексте. Некоторые операции способны распознавать в каком контексте они исполняются и возвращать свой результат в зависимости от него (универсальные операции). Например, если рассматривать @ как унарную операцию обращения к массиву, то в скалярном контексте она возвращает число элементов в массиве, а в списковом контексте — список из элементов массива.

# В списковой операции перед списком можно указать выходной дескриптор: 
print STDOUT (2 + 2 * 25 / 4, ' ', 16) . '$'; # Напечатает '16$'
# Потеря 14.5 Объясняется тем, что левый операнд конкатенации 
# находится в скалярном контексте, а в нем операция запятая
# возвращает последний операнд как результат.

# Уберем скобки:
print STDOUT 2 + 2 * 25 / 4, ' ', 16 . '$'; # Напечатает '14.5 16$'
# Теперь каждый элемент списка это терм, который после вычисления,
# передается списковой операции.

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

Еще один специальный скалярный контекст — булевый. Так как в Perl нет булева true или false, Perl анализирует строки и числа в булевом контексте, как это было описано выше: 0, "0", "00", "0.0" и "" это условно ЛОЖЬ, а все остальное ИСТИНА.

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

(1,2,3);
$n;
"Hello";

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

Еще один контекст это подстановочный контекст, в котором вычисляются операции заключения в кавычки (кроме одинарных кавычек). В этом контексте подставляются переменные и интерпретируются управляющие последовательности.

Ниже для справки представлены приоритеты операций.

Приоритет Операция Сочетаемость
1 Вычисление термов и левосторонних списковых операций Слева направо
2 -> Слева направо
3 ++ -- Не сочетаются
4 ** Справа налево
5 ! ~ \ унарный + унарный - Справа налево
6 =~ != Слева направо
7 * / % x Слева направо
8 + - . Слева направо
9 << >> Слева направо
10 Именованные унарные операции Не сочетаются
11 < > <= >= lt gt le ge Не сочетаются
12 == != <=> eq ne cmp Не сочетаются
13 & Слева направо
14 | ^ Слева направо
15 && Слева направо
16 || Слева направо
17 .. ... Не сочетаются
18 ?: Справа налево
19 = **= += -= .= *= /= %= x= &= |= ^= <<= >>= &&= ||= Справа налево
20 , => Слева направо
21 Правосторонние списковые операции Не сочетаются
22 not Справа налево
23 and Слева направо
24 or xor Слева направо
  • В данной таблице чем выше приоритет операции и чем левее она стоит (в большинстве случаев), тем раньше она выполняется.
  • Приоритет списковой операции зависит от ее места в выражении и может изменяться от наивысшего к наименьшему. Все операции в выражении, стоящие слева от списковой, имеют наивысший приоритет по отношению к ней (смотрите 21 приоритет).
  • Свойство сочетаемости означает, что операции одного приоритета могут быть в одном выражении, причем порядок их разрешения может быть слева направо или справа налево.
  • Скобки позволяют изменить порядок вычисления, определяемому в обычных условиях приоритетом и сочетаемостью. Скобки всегда наделяют выражение в них наивысшим приоритетом.



← Типы данных Операторы →