Сравнение скаляров в Perl
В предыдущей части Учебника Perl мы познакомились со скалярами и узнали, как числа и строки конвертируются друг в друга на лету. Мы даже мельком взглянули на условное выражение 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 = <STDIN>; chomp $name; if ( $name == "" ) { # неверно! здесь нужно использовать eq вместо == ! say "TRUE"; } else { say "FALSE"; }
Если запустить этот скрипт и ввести "abc", мы получим ответ TRUE, так как perl решил, что "abc" это то же, что и пустая строка.

Published on 2013-10-14