开发者

How to validate number in perl?

开发者 https://www.devze.com 2023-03-04 22:36 出处:网络
I know that there is a library that do that use Scalar::Util qw(looks_like_number); yet I want to do it using perl regular expression. And I want it to work for double numbers not for only integer

I know that there is a library that do that

use Scalar::Util qw(looks_like_number);

yet I want to do it using perl regular expression. And I want it to work for double numbers not for only integers.

so I want something better than this

$var =开发者_Python百科~ /^[+-]?\d+$/

thanks.


Constructing a single regular expression to validate a number is really difficult. There simply are too many criteria to consider. Perlfaq4 contains a section "How do I determine whether a scalar is a number/whole/integer/float?

The code from that documentation shows the following tests:

if (/\D/)                          {print "has nondigits\n"      }
if (/^\d+$/)                       {print "is a whole number\n"  }
if (/^-?\d+$/)                     {print "is an integer\n"      }
if (/^[+-]?\d+$/)                  {print "is a +/- integer\n"   }
if (/^-?\d+\.?\d*$/)               {print "is a real number\n"   }
if (/^-?(?:\d+(?:\.\d*)?|\.\d+)$/) {print "is a decimal number\n"}
if (/^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/) {
    print "is a C float\n"
}
  • The first test disqualifies an unsigned integer.
  • The second test qualifies a whole number.
  • The third test qualifies an integer.
  • The fourth test qualifies a positive/negatively signed integer.
  • The fifth test qualifies a real number.
  • The sixth test qualifies a decimal number.
  • The seventh test qualifies a number in c-style scientific notation.

So if you were using those tests (excluding the first one) you would have to verify that one or more of the tests passes. Then you've got a number.

Another method, since you don't want to use the module Scalar::Util, you can learn from the code IN Scalar::Util. The looks_like_number() function is set up like this:

sub looks_like_number {
  local $_ = shift;

  # checks from perlfaq4
  return $] < 5.009002 unless defined;
  return 1 if (/^[+-]?\d+$/); # is a +/- integer
  return 1 if (/^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/); # a C float
  return 1 if ($] >= 5.008 and /^(Inf(inity)?|NaN)$/i) 
           or ($] >= 5.006001 and /^Inf$/i);

  0;
}

You should be able to use the portions of that function that are applicable to your situation.

I would like to point out, however, that Scalar::Util is a core Perl module; it ships with Perl, just like strict does. The best practice of all is probably to just use it.


You should use Regexp::Common, most patterns are more complicated than you realize.

use Regexp::Common;

my $real = 3.14159;
print "Real" if $real =~ /$RE{num}{real}/;

However, the pattern is not anchored by default, so a stricter version is:

my $real_pat = $RE{num}{real};
my $real     = 3.14159;
print "Real" if $real =~ /^$real_pat$/;


Well first you should make sure that the number does not contain any commas so you do this:

$var =~ s/,//g; # remove all the commas

Then create another variable to do the rest of the compare.

$var2=$var;

Then remove the . from the new variable yet only once occurrence.

$var2 =~ s/.//; # replace . with nothing to compare yet only once.

now var2 should look like an integer with no "." so do this:

    if($var2 !~ /^[+-]?\d+$/){
        print "not valid";
    }else{
       #use var1 
    }

you can fix this code and write it as a function if you need to use it more than once. Cheers!

0

精彩评论

暂无评论...
验证码 换一张
取 消