【问题标题】:Checking version number validity with Perl使用 Perl 检查版本号的有效性
【发布时间】:2009-05-14 08:41:54
【问题描述】:

我正在努力检查 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(er) 吗?确保最多可以有一个“er”?为什么不 0{1}。只匹配“0.”,而不是接受“01.”也一样?

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

【问题讨论】:

    标签: regex perl


    【解决方案1】:

    您的问题是 or - | - 您正在使用将整个模式一分为二。 | 将作用于括号或表达式的结尾,而不仅仅是两个相邻项。

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

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

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

    另外,{1} 是不必要的,它意味着上一个项目恰好一次,这是默认值。但是,您可以在模式的末尾使用 {3},因为您希望最后三个点位组。

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

    我们也可以去掉多余的括号。

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

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

    【讨论】:

      【解决方案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
      

      【讨论】:

        【解决方案3】:

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

        • 自己没试过
        • 好像最新的模块发布是在 2007 年 - 有点让它成为一个递归问题

        【讨论】:

        • 虽然我总是喜欢推荐 CPAN,但 Perl::Version 在这里并不合适。它旨在解析 CPAN 模块使用的版本号,而 Makis 正在尝试验证不同的版本格式。 (他只是在 Perl 中编写检查代码。)
        猜你喜欢
        • 2011-11-07
        • 2012-08-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多