用于版本号解析的正则表达式
我有以下形式的版本号:
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
但是这些无效:
*.12 *123.1 12* 12.*.34
谁能为我提供一个不太复杂的正则表达式来验证和检索版本号,版本号和修改号?
解决方案
回答
这可能起作用:
^(\*|\d+(\.\d+){0,2}(\.\*)?)$
在顶层," "是有效版本号的特例。否则,它以数字开头。然后有零个,一个或者两个" .nn"序列,后跟一个可选的"。"。此正则表达式将接受1.2.3. *,这可能会或者可能不会在应用程序中允许。
检索匹配序列的代码,特别是(\。\ d +){0,2}
部分,将取决于特定正则表达式库。
回答
使用正则表达式,现在有两个问题。我将东西分割成点("。"),然后确保每个部分都是通配符或者数字集(正则表达式现在很完美)。如果事物是有效的,则只需返回正确的拆分块。
回答
我将格式表示为:
"1-3 dot-separated components, each numeric except that the last one may be *"
作为正则表达式,那就是:
^(\d+\.)?(\d+\.)?(\*|\d+)$
[编辑添加:此解决方案是一种简洁的验证方法,但已指出,提取值需要额外的工作。是否通过使正则表达式复杂化或者处理匹配的组来解决这个问题。
在我的解决方案中,组捕获"。"字符。这可以通过使用非捕获组来解决,如ajborley的答案。
同样,即使少于三个组件,最右边的组也将捕获最后一个组件,因此,例如,两分量的输入将导致第一个和最后一个组被捕获,而中间的一个则未定义。我认为可以通过支持的非贪婪团体来解决。
在正则表达式之后处理这两个问题的Perl代码可能是这样的:
@version = (); @groups = (, , ); foreach (@groups) { next if !defined; s/\.//; push @version, $_; } ($major, $minor, $mod) = (@version, "*", "*");
这实际上并不比在`"上分割要短。
]
回答
请记住,regexp是贪婪的,因此,如果我们只是在版本号字符串中而不是在较大的文本中进行搜索,请使用^和$标记字符串的开始和结束。
Greg的regexp似乎工作正常(在我的编辑器中进行了快速尝试),但是根据库/语言,第一部分仍可以在错误的版本号中匹配" *"。也许我缺少了一些东西,因为我已经有大约一年没有使用Regexp了。
这应该确保我们只能找到正确的版本号:
^(\ * | \ d +(\。\ d +)*(\。\ *)?)$
编辑:实际上greg已经添加了它们,甚至改进了他的解决方案,我太慢了:)
回答
我倾向于同意分开的建议。
Ive为我们在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 = if ( && ne "*") ; $maj = if ( && ne "*") ; $min = if ( && ne "*") ; $rev = if ( && ne "*") ; $ex1 = if ( && ne "*") ; $ex2 = if ( && ne "*") ; $ex3 = if ( && ne "*") ; print "$main $maj $min $rev $ex1 $ex2 $ex3\n"; }else{ print " nomatch\n"; } } print "------------------------\n"; }
电流输出:
> 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 ------------------------
回答
(?ms)^((?:\d+(?!\.\*)\.)+)(\d+)?(\.\*)?$|^(\d+)\.\*$|^(\*|\d+)$
与前6个示例完全匹配,并拒绝其他4个示例
- 第1组:major或者major.minor或者'*'
- 第2组(如果存在):未成年人或者*
- 第3组(如果存在):*
我们可以删除"(?ms)"
我用它来表示此正则表达式将通过QuickRex应用于多行
回答
不知道我们使用的平台是什么,但是.NET中有System.Version类,它将为我们解析" n.n.n.n"版本号。
回答
这也匹配1.2.3. *
^(*|\d+(.\d+){0,2}(.*)?)$
我会提出不太优雅的建议:
(* | \ d +(。\ d +)?(。*)?)| \ d +。\ d +。\ d +)
回答
感谢所有回复!这是王牌:)
根据OneByOne的回答(对我来说,这似乎是最简单的),我添加了一些非捕获组(感谢VonC将我介绍给非捕获组,所以其中的'(?:'部分)!数字或者*字符。
^(?:(\d+)\.)?(?:(\d+)\.)?(\*|\d+)$
非常感谢大家!
回答
另一种尝试:
^(((\d+)\.)?(\d+)\.)?(\d+|\*)$
这给出了组4,5,6 BUT中的三个部分:
它们向右对齐。因此,4,5或者6中的第一个非空值将给出version字段。
- 1.2.3给出1,2,3
- 1.2. 给出1,2,
- 1.2给出null,1,2
- **给出null,null,
- 给出null,1,
回答
正则表达式似乎很难满足要求(即仅接受我们需要的情况,拒绝所有其他情况,并为这三个组成部分返回一些组),这似乎非常困难。我尝试一下,并提出以下建议:
^(\*|(\d+(\.(\d+(\.(\d+|\*))?|\*))?))$
IMO(我尚未进行广泛的测试),它可以很好地用作输入的验证器,但问题是此正则表达式无法提供检索组件的方法。为此,我们仍然必须进行分割。
这种解决方案不是一站式的,但是在编程中多数时候并不需要。当然,这取决于代码中可能存在的其他限制。
回答
^(?:(\d+)\.)?(?:(\d+)\.)?(\*|\d+)$
也许更简洁一些:
^(?:(\d+)\.){0,2}(\*|\d+)$
然后可以将其增强为1.2.3.4.5. 或者使用或者{2}而不是{0,2}严格限制为X.Y.Z
回答
这应该符合规定。它取决于通配符位置,并且是嵌套的正则表达式:
^((\*)|([0-9]+(\.((\*)|([0-9]+(\.((\*)|([0-9]+)))?)))?))$