Checking the correct version number with Perl

I am trying to check the correct version numbers in Perl. The correct version number is as follows:

  • Starts with v or ver,
  • After that, the number, if it is 0, then no other numbers are allowed in that part (e.g. 10, 3993 and 0 are ok, 01 is not),
  • Thereafter, full stop, number, full stop, number, full stop and number.

those. a valid version number might look something like v0.123.45.678 or ver18.493.039.1.

The following regexp came up:

if ($ver_string !~ m/^v(er)?(0{1}\.)|([1-9]+\d*\.)\d+\.\d+\.\d+/) 
{
   #print error
}

      

But it doesn't work because a version number such as verer01.34.56.78 is accepted. I can't figure it out, I know Perl tends to be greedy, but shouldn't it (v)? make sure there can be at most one "er"? And why not 0 {1}. matches only "0." instead of accepting "01". also?

Is this regex really hooked on the "rere" thing: m / ^ v (er)? [0-9.] + /, But I don't see where I resolve this in my attempt.

+1


a source to share


3 answers


Your problem is that what you are using or - |

is splitting the whole template in two. A |

will span parentheses or the end of an expression, not just two adjacent elements.

You need to add a few extra parentheses to indicate which part of the expression you want or -ed. So, the first step to fix your template would be:

^v(er)?((0{1}\.)|([1-9]+\d*\.))\d+\.\d+\.\d+

      

You also want to $

end up to make sure there are no false characters at the end of the version number.

Also, no placement {1}

is needed, which means that the previous element is exactly once, which is the default. However, you can use it {3}

at the end of your pattern, as you should have three dotted groups at the end.



Likewise, you don't need +

after [1-9]

as other digits will be captured \d*

.

And we can also remove the neon brackets.

So, you can simplify your patten like this:

^v(er)?(0|[1-9]\d*)(.\d+){3}$

      

+7


a source


You can do it with one regex, or you can do it in 2 steps, the second step is to check that the first number does not start with 0.

By the way, I usually use [0-9] instead of \ d for numbers, there are many characters that are classified as numbers in the Unicode standard (and therefore Perl) that you might not want to deal with.



Here is some sample code, subcategory version_ok, where everything happens.

#!/usr/bin/perl

use strict;
use warnings;

use Test::More tests => 7;

while( <DATA>) 
  { chomp; 
    my( $version, $expected)= split /\s*=>\s*/;
    is( version_ok( $version), $expected, $version);
  }

sub version_ok  
  { my( $version)=@_;
    if( $version=~ m{^v(?:er)?        # starts with v or ver
                      ([0-9]+)        # the first number
                      (?:\.[0-9]+){3} # 3 times dot number
                     $}x)             # end
      { if( $1 =~ m{^0[0-9]})         
          { return 0; }               # no good: first number starts with 0
        else 
          { return 1; } 
      } 
    else
      { return 0; }
  }


__DATA__
v0.123.45.678      => 1
ver18.493.039.1    => 1
verer01.34.56.78   => 0
v01.5.5.5          => 0
ver101.5.5.5       => 1
ver101.5.5.        => 0
ver101.5.5         => 0

      

+1


a source


A regex might work for your test cases, but the CPAN Perl :: Version module looks like a better option, with two caveats

  • haven't tried it myself.
  • looks like the last release of the module was in 2007 - sort of like a recursive problem.
0


a source







All Articles