Как Perl преобразует строки в числа

Любую строку в языке программирования Perl можно использовать в качестве числа. Вот пример:

▶ Run
#!/usr/bin/perl

my $str = 'Hello';

print $str + 100;

Программа выведет на экран число 100. Строка 'Hello' при использовании в арифметической операции — это число 0. Число 0 плюс 100 будет 100 и именно это мы увидим на экране. Часто используются слова "числовой контекст" для обозначения что значение в операции используется как число.

Строка 'Hello' в числовом контексте это 0. Но не все строки в Perl являются нулем.

В том случае если в начале строки идут цифры, то числом становится совокупность этих цифр. Вот пример:

▶ Run
#!/usr/bin/perl

my $str = '23ASDF';

print $str + 0;

Программа выведет на экран число 23.

Вот еще несколько примеров, строка и число в которое оно превращается при использовании в числовом контексте:

''          -> 0
'1.0ASDF'   -> 1
'1.2ADF'    -> 1.2
'0123ASDF'  -> 123
' 34ASDF'   -> 34
'0x13ABC'   -> 0
'0b10ABC'   -> 0
'1e+25ASDF' -> 1e+25
' +7ASDF'   -> 7
'-13ABC'    -> -13
'--13ABC'   -> 0
' 10 100'   -> 10

Вот скрипт, который выведет эти же данные:

▶ Run
#!/usr/bin/perl

use feature qw(say);

foreach my $str ('', '1.0ASDF', '1.2ADF', '0123ASDF', ' 34ASDF',  '0x13ABC', '0b10ABC', '1e+25ASDF', ' +7ASDF', '-13ABC', '--13ABC', ' 10 100') {
     say "'$str' -> " . ($str + 0);
}

use warnings;

Если в Perl скрипте есть use warnings; (что практически всегда стоит делать), то тогда использование строки в числовом контексте выведет на STDERR предупреждение:

▶ Run
#!/usr/bin/perl

use strict;
use warnings;

my $str = 'Hello';

print $str + 100;

Вот вывод программы:

Argument "Hello" isn't numeric in addition (+) at script.pl line 8.
100

Рекомендация

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

Вот пример кода. Мы точно знаем про данные что в самом начале строке находится целое число и нам нужно посчитать сумму всех чисел во всех строках.

▶ Run
#!/usr/bin/perl

use strict;
use warnings;

my @strings = (
    '10 apples',
    '0 potatoes',
    '8 oranges',
    'nine lemons',
);

my $sum = 0;

foreach my $str (@strings) {
    if ($str =~ /^([0-9]+)/) {
        $sum += $1;
    } else {
        die "String '$str' is in incorrect format";
    }
}

print $sum;

При запуске этой программы мы получим ошибку String 'nine lemons' is in incorrect format at script.pl line 19.. Благодаря этому мы видим что в данных есть проблема. В зависимости о того как правильно, мы можем либо поправить данные, вместо строки 'nine lemons' использовать строку '9 lemons', либо можем явно игнорировать эту строку в цикле next if $str eq 'nine lemons'.

Если бы мы воспользовались стандартным средством Perl по преобразования строки в число, то цикл был бы гораздо проще:

foreach my $str (@strings) {
    $sum += $str;
}

Но в этом случае мы бы не узнали что данные не соответствуют тому формату который мы ожидаем.

Другие статьи

Комментарии