Вопрос по perl, numbers – Как мне узнать, имеет ли переменная числовое значение в Perl?
Похоже, вы хотите знать, считает ли Perl переменную числовой. Вот функция, которая перехватывает это предупреждение:
sub is_number{
my $n = shift;
my $ret = 1;
$SIG{"__WARN__"} = sub {$ret = 0};
eval { my $x = $n + 1 };
return $ret
}
Другой вариант - отключить предупреждение локально:
{
no warnings "numeric"; # Ignore "isn't numeric" warning
... # Use a variable that might not be numeric
}
Обратите внимание, что нечисловые переменные будут автоматически преобразованы в 0, что, вероятно, в любом случае вам и нужно.
как определить, является ли переменная числовой, а не имеет ли она «числовое значение».
Есть несколько операторов, которые имеют отдельные режимы работы для числовых и строковых операндов, где & quot; числовые & quot; означает все, что изначально было числом или когда-либо использовалось в числовом контексте (например, в$x = "123"; 0+$x
перед добавлением,$x
является строкой, после чего она считается числовой).
Один из способов сказать это:
if ( length( do { no warnings "numeric"; $x & "" } ) ) {
print "$x is numeric\n";
}
sub numeric { my $obj = shift; no warnings "numeric"; return length($obj & ""); }
print numeric("w") . "\n"; #=>0
, print numeric("x") . "\n"; #=>0
, print numeric("1") . "\n"; #=>0
, print numeric(3) . "\n"; #=>1
, print numeric("w") . "\n"; #=>1
, Если вы поместите eval ('' ') вокруг длины, последний отпечаток даст 0, как и должно быть. Пойди разберись.
sub numeric { $obj = shift; no warnings "numeric"; return eval('length($obj & "")'); }
my $obj = shift
конечно, просто неправильно перенес это из моего кода в комментарий, я его немного отредактировал. Тем не мение,sub numeric { my $obj = shift; no warnings "numeric"; return length($obj & ""); }
выдает ту же ошибку. Конечно, наличие скрытой глобальной переменной могло бы объяснить поведение, это именно то, чего я ожидал бы в этом случае, но, к сожалению, все не так просто. Кроме того, это будет пойманstrict
& Амп;warnings
, Я попробовал eval в довольно отчаянной попытке избавиться от ошибки, и это сработало. Нет более глубоких рассуждений, просто пробная версия ошибка.
т код будет определять, является ли что-то числовым, а также проверять неопределенные переменные, чтобы не выдавать предупреждения:
sub is_integer {
defined $_[0] && $_[0] =~ /^[+-]?\d+$/;
}
sub is_float {
defined $_[0] && $_[0] =~ /^[+-]?\d+(\.\d+)?$/;
}
Вот некоторыематериал для чтения Вы должны посмотреть.
\d*\.?\d+
часть вводитReDoS риск. рекомендую/^[+-]?(?!\.(?!\d)|$)\d*(?:\.\d*)?$/
или же/^[+-]?(?!\.(?!\d)|$)\d*(?:\.\d*)?(?:(?<=[\d.])e[+-]?\d+)?$/i
включить научную запись (explanation and examples) вместо Это использует двойное отрицательное предпросмотр, чтобы также предотвратить такие строки, как.
а также.e0
от прохождения как числа. Он также использует позитивный взгляд заe
следует за номером.
что для этого нужно полагаться на внутренний контекст Perl, чтобы сделать решение пуленепробиваемым. Хорошее регулярное выражение может соответствовать всем действительным числовым значениям и ни одному из нечисловых (или наоборот), но, поскольку существует способ использовать ту же логику, которую использует интерпретатор, она должна быть более безопасной, чтобы полагаться на нее напрямую.
Как я склонен запускать свои сценарии с-w
Мне пришлось объединить идею сравнения результата «значение плюс ноль». к первоначальному значению сno warnings
основанный на @ysth подход:
do {
no warnings "numeric";
if ($x + 0 ne $x) { return "not numeric"; } else { return "numeric"; }
}
sub IS_Integer()
{
my $Text = shift;
my $Integer = 0;
if ($Text =~ /\D/)
{
$Integer = 1;
}
if ($Text =~ /^\d+$/)
{
$Integer = 1;
}
if ($Text =~ /^-?\d+$/)
{
$Integer = 1;
}
if ($Text =~ /^[+-]?\d+$/)
{
$Integer = 1;
}
if ($Text =~ /^-?\d+\.?\d*$/)
{
$Integer = 1;
}
if ($Text =~ /^-?(?:\d+(?:\.\d*)?&\.\d+)$/)
{
$Integer = 1;
}
if ($Text =~ /^([+-]?)(?=\d&\.\d)\d*(\,.\d*)?([Ee]([+-]?\d+))?$/)
{
$Integer = 1;
}
return $Integer;
}
использованиеScalar::Util::looks_like_number()
которая использует внутреннюю функцию Perl C API look_like_number (), которая, вероятно, является наиболее эффективным способом сделать это.
Обратите внимание, что строки "inf" и «бесконечность»; рассматриваются как числа.
#!/usr/bin/perl
use warnings;
use strict;
use Scalar::Util qw(looks_like_number);
my @exprs = qw(1 5.25 0.001 1.3e8 foo bar 1dd inf infinity);
foreach my $expr (@exprs) {
print "$expr is", looks_like_number($expr) ? '' : ' not', " a number\n";
}
Дает этот вывод:
1 is a number
5.25 is a number
0.001 is a number
1.3e8 is a number
foo is not a number
bar is not a number
1dd is not a number
inf is a number
infinity is a number
See also:
perldoc Scalar::Util
perldoc perlapi for looks_like_number
perldoc perlapi
говорит нам: Проверьте, выглядит ли содержимое SV как число (или число). & Quot; Inf & Quot; и & quot; Бесконечность & quot; обрабатываются как числа (поэтому не будут выдавать нечисловое предупреждение), даже если ваш atof () их не обманывает. Вряд ли тестируемая спецификация ...
что для этого есть что-то встроенное. Больше, чем вы когда-либо хотели увидеть по этому вопросу, смотритеPerlmonks по обнаружению числовых
или же $ x = 0, если! $ Х; if ($ x! ~ m / \ D /) {}
Это небольшое изменение в ответе Veekay, но позвольте мне объяснить мои аргументы в пользу такого изменения.
Выполнение регулярного выражения для неопределенного значения приведет к возникновению ошибки и к выходу кода во многих, если не в большинстве сред. Проверка, определено ли значение или установка регистра по умолчанию, как я делал в альтернативном примере, перед запуском выражения, как минимум, сохранит ваш журнал ошибок.
чтобы определить, является ли $ foo числом (или нет).
Посмотрите здесь: Как определить, является ли скаляр числом
Regexp :: Общие, Я думаю, что он делает именно то, что вам нужно, и обрабатывает все крайние случаи (например, действительные числа, научные записи и т. Д.). например
use Regexp::Common;
if ($var =~ /$RE{num}{real}/) { print q{a number}; }