我正在努力检查Perl中版本号的有效性。正确的版本号是这样的:
即。有效的版本号可能类似于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。] + /但是在我的尝试中我无法看到我允许它的位置。
答案 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似乎是最佳选择,有两点需要注意: