使用Perl检查版本号有效性

时间:2009-05-14 08:41:55

标签: regex perl

我正在努力检查Perl中版本号的有效性。正确的版本号是这样的:

  • 以v或ver开头,
  • 之后是一个数字,如果它是0,那么这个部分不允许其他数字(例如10,3993和0都可以,01不是),
  • 之后是句号,句号,句号,号码,句号和号码。

即。有效的版本号可能类似于v0.123.45.678或ver18.493.039.1。

我想出了以下正则表达式:

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

但这不起作用,因为版本号如verer01.34.56.78被接受。我无法理解这一点,我知道Perl往往是贪心,但不应该^ v(呃)?确保最多只能有一个“呃”?为什么不是0 {1}。仅匹配“0”,而不是接受“01”。还有吗?

这个正则表达式实际上抓住了“rere”的东西:m / ^ v(呃)?[0-9。] + /但是在我的尝试中我无法看到我允许它的位置。

3 个答案:

答案 0 :(得分:7)

你的问题是你正在使用的or - |将整个模式分成两部分。 |将括号范围或表达式的结尾,而不仅仅是两个相邻项目。

你需要加上一些额外的括号,两个显示你想要的表达式的哪个部分。因此,修复模式的第一步是:

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

您还希望在末尾添加$,以确保版本号末尾没有虚假字符。

此外,不需要{1},这意味着前一项只是默认的一次。但是,您可以在模式的末尾使用{3},因为您最后需要三个点数组。

同样,+之后您不需要[1-9],因为\d*会抓取其他数字。

我们也可以删除不一致的括号。

因此,您可以将您的模式简化为以下内容:

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

答案 1 :(得分:1)

你可以用一个正则表达式来完成,或者你可以分2步完成,第二步是检查第一个数字是不是以0开头。

顺便说一句,我倾向于使用[0-9]而不是\ d来表示数字,有许多字符被归类为Unicode标准中的数字(因此在Perl中),您可能不想处理它们。

这是一个示例代码,version_ok sub是一切发生的地方。

#!/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

答案 2 :(得分:0)

正则表达式可能适用于您的测试用例,但CPAN模块Perl::Version似乎是最佳选择,有两点需要注意:

  • 自己没有尝试过
  • 似乎最新的模块发布于2007年 - 有点使其成为一个递归问题