版本号解析的正则表达式

And*_*ley 73 regex versioning

我有以下形式的版本号:

version.release.modification

其中版本,发布和修改是一组数字或'*'通配符.此外,这些数字(以及任何前面的数字)中的任何一个都可能丢失.

所以以下是有效的并解析为:

1.23.456 = version 1, release 23, modification 456
1.23     = version 1, release 23, any modification
1.23.*   = version 1, release 23, any modification
1.*      = version 1, any release, any modification
1        = version 1, any release, any modification
*        = any version, any release, any modification
Run Code Online (Sandbox Code Playgroud)

但这些都无效:

*.12
*123.1
12*
12.*.34
Run Code Online (Sandbox Code Playgroud)

任何人都可以为我提供一个不太复杂的正则表达式来验证和检索版本,版本和修改号码吗?

Ste*_*sop 80

我将格式表达为:

"1-3个点分隔的组件,每个数字除了最后一个可能是*"

作为正则表达式,那是:

^(\d+\.)?(\d+\.)?(\*|\d+)$
Run Code Online (Sandbox Code Playgroud)

[编辑添加:此解决方案是一种简洁的验证方式,但有人指出,提取值需要额外的工作.无论是通过使正则表达式复杂化还是通过处理匹配的组来处理这个问题,都是一个品味问题.

在我的解决方案中,组捕获"."角色.这可以使用非捕获组来处理,就像在ajborley的回答中一样.

此外,最右边的组将捕获最后一个组件,即使组件少于三个,因此例如双组件输入导致第一组和最后一组捕获而中间组未定义.我认为这可以由支持的非贪婪团体来处理.

在regexp之后处理这两个问题的Perl代码可能是这样的:

@version = ();
@groups = ($1, $2, $3);
foreach (@groups) {
    next if !defined;
    s/\.//;
    push @version, $_;
}
($major, $minor, $mod) = (@version, "*", "*");
Run Code Online (Sandbox Code Playgroud)

这是不是真的比分裂的任何短"." ]


Paw*_*dan 39

使用正则表达式,现在你有两个问题.我会把东西分成点("."),然后确保每个部分都是通配符或一组数字(正则表达式现在是完美的).如果该东西有效,您只需返回正确的分割块.


Gre*_*ill 11

这可能有效:

^(\*|\d+(\.\d+){0,2}(\.\*)?)$
Run Code Online (Sandbox Code Playgroud)

在顶层,"*"是有效版本号的特例.否则,它以数字开头.然后有零个,一个或两个".nn"序列,后跟一个可选的".*".此正则表达式将接受1.2.3.*,这可能会或可能不会在您的申请中被允许.

检索匹配序列的代码,尤其是(\.\d+){0,2}部分,取决于您的特定正则表达式库.

  • 彼得:我想我现在要停下来.这很快就会进入"现在你有两个问题"的领域.:) (2认同)

And*_*ley 11

感谢所有的回复!这是王牌:)

基于OneByOne的答案(对我来说看起来最简单),我添加了一些非捕获组('(?:'部分 - 感谢VonC向我介绍非捕获组!),因此只捕获组的组包含数字或*字符.

^(?:(\d+)\.)?(?:(\d+)\.)?(\*|\d+)$
Run Code Online (Sandbox Code Playgroud)

非常感谢大家!

  • 您可以将此作为编辑添加到您的问题中吗?这样正确答案就接近顶部 (2认同)

Dun*_*art 7

不知道你在哪个平台,但在.NET中有System.Version类,它将为你解析"nnnn"版本号.


Sud*_*hra 7

我的2美分:我遇到过这种情况:我不得不用字符串文字解析版本号.(我知道这与原始问题有很大不同,但谷歌搜索找到解析版本号的正则表达式显示此顶部的线程,所以在这里添加这个答案)

所以字符串文字将是这样的:"服务版本1.2.35.564正在运行!"

我不得不解析这个字面上的1.2.35.564.从@ajborley那里得到一个提示,我的正则表达式如下:

(?:(\d+)\.)?(?:(\d+)\.)?(?:(\d+)\.\d+)
Run Code Online (Sandbox Code Playgroud)

一个小的C#片段来测试它如下所示:

void Main()
{
    Regex regEx = new Regex(@"(?:(\d+)\.)?(?:(\d+)\.)?(?:(\d+)\.\d+)", RegexOptions.Compiled);

    Match version = regEx.Match("The Service SuperService 2.1.309.0) is Running!");
    version.Value.Dump("Version using RegEx");   // Prints 2.1.309.0        
}
Run Code Online (Sandbox Code Playgroud)


小智 6

我看过很多答案,但是……我有一个新答案。至少对我有用。我添加了一个新的限制。版本号不能以任何零开头(主要、次要或补丁)。

01.0.0 无效 1.0.0 有效 10.0.10 有效 1.0.0000 无效

^(?:(0\\.|([1-9]+\\d*)\\.))+(?:(0\\.|([1-9]+\\d*)\\.))+((0|([1-9]+\\d*)))$
Run Code Online (Sandbox Code Playgroud)

它基于前一个。但我认为这个解决方案更好......对我来说;)

享受!!!


Shi*_*iva 6

我需要搜索/匹配版本号,这遵循 maven 约定,甚至只是一位数。但无论如何都没有限定词。这很奇怪,我花了一些时间才想出这个:

'^[0-9][0-9.]*$'
Run Code Online (Sandbox Code Playgroud)

这可以确保版本,

  1. 以数字开头
  2. 可以有任意数量的数字
  3. 只有数字和“.” 被允许

一个缺点是版本甚至可以以 '.' 结尾。但它可以处理无限长度的版本(如果你想称之为疯狂的版本控制)

火柴:

  • 1.2.3
  • 1.09.5
  • 3.4.4.5.7.8.8。
  • 23.6.209.234.3

如果您对“.”不满意 结尾,也许你可以与逻辑结合


svr*_*ist 5

我倾向于同意拆分建议.

我在perl中为你的问题创建了一个"测试器"

#!/usr/bin/perl -w


@strings = ( "1.2.3", "1.2.*", "1.*","*" );

%regexp = ( svrist => qr/(?:(\d+)\.(\d+)\.(\d+)|(\d+)\.(\d+)|(\d+))?(?:\.\*)?/,
            onebyone => qr/^(\d+\.)?(\d+\.)?(\*|\d+)$/,
            greg => qr/^(\*|\d+(\.\d+){0,2}(\.\*)?)$/,
            vonc => qr/^((?:\d+(?!\.\*)\.)+)(\d+)?(\.\*)?$|^(\d+)\.\*$|^(\*|\d+)$/,
            ajb => qr/^(?:(\d+)\.)?(?:(\d+)\.)?(\*|\d+)$/,
            jrudolph => qr/^(((\d+)\.)?(\d+)\.)?(\d+|\*)$/
          );

  foreach my $r (keys %regexp){
    my $reg = $regexp{$r};
    print "Using $r regexp\n";
foreach my $s (@strings){
  print "$s : ";

    if ($s =~m/$reg/){
    my ($main, $maj, $min,$rev,$ex1,$ex2,$ex3) = ("any","any","any","any","any","any","any");
    $main = $1 if ($1 && $1 ne "*") ;
    $maj = $2 if ($2 && $2 ne "*") ;
    $min = $3 if ($3 && $3 ne "*") ;
    $rev = $4 if ($4 && $4 ne "*") ;
    $ex1 = $5 if ($5 && $5 ne "*") ;
    $ex2 = $6 if ($6 && $6 ne "*") ;
    $ex3 = $7 if ($7 && $7 ne "*") ;
    print "$main $maj $min $rev $ex1 $ex2 $ex3\n";

  }else{
  print " nomatch\n";
  }
  }
print "------------------------\n";
}
Run Code Online (Sandbox Code Playgroud)

当前输出:

> perl regex.pl
Using onebyone regexp
1.2.3 : 1. 2. 3 any any any any
1.2.* : 1. 2. any any any any any
1.* : 1. any any any any any any
* : any any any any any any any
------------------------
Using svrist regexp
1.2.3 : 1 2 3 any any any any
1.2.* : any any any 1 2 any any
1.* : any any any any any 1 any
* : any any any any any any any
------------------------
Using vonc regexp
1.2.3 : 1.2. 3 any any any any any
1.2.* : 1. 2 .* any any any any
1.* : any any any 1 any any any
* : any any any any any any any
------------------------
Using ajb regexp
1.2.3 : 1 2 3 any any any any
1.2.* : 1 2 any any any any any
1.* : 1 any any any any any any
* : any any any any any any any
------------------------
Using jrudolph regexp
1.2.3 : 1.2. 1. 1 2 3 any any
1.2.* : 1.2. 1. 1 2 any any any
1.* : 1. any any 1 any any any
* : any any any any any any any
------------------------
Using greg regexp
1.2.3 : 1.2.3 .3 any any any any any
1.2.* : 1.2.* .2 .* any any any any
1.* : 1.* any .* any any any any
* : any any any any any any any
------------------------
Run Code Online (Sandbox Code Playgroud)


ofa*_*rax 5

^(?:(\d+)\.)?(?:(\d+)\.)?(\*|\d+)$
Run Code Online (Sandbox Code Playgroud)

也许更简洁的可能是:

^(?:(\d+)\.){0,2}(\*|\d+)$
Run Code Online (Sandbox Code Playgroud)

然后可以将其增强到 1.2.3.4.5.* 或使用 * 或 {2} 而不是 {0,2} 完全限制为 XYZ


小智 5

这应该适用于您的规定。它取决于通配符位置并且是一个嵌套的正则表达式:

^((\*)|([0-9]+(\.((\*)|([0-9]+(\.((\*)|([0-9]+)))?)))?))$
Run Code Online (Sandbox Code Playgroud)

http://imgur.com/3E492.png


peg*_*peg 5

用于解析遵循以下规则的版本号: - 仅是数字和点 - 不能以点开头或结尾 - 不能是两个点在一起

这个对我来说很有效。

^(\d+)((\.{1}\d+)*)(\.{0})$
Run Code Online (Sandbox Code Playgroud)

有效案例有:

1、0.1、1.2.1