版本号parsing的正则expression式
我有以下forms的版本号:
version.release.modification
版本,发布和修改是一组数字或'*'通配符。 此外,任何这些数字(和任何前面的)可能会丢失。
所以以下是有效的和parsing为:
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
任何人都可以提供一个不太复杂的正则expression式来validation和检索版本号和修改号吗?
非常感谢!
感谢所有的回应! 这是王牌:)
基于OneByOne的回答(对我来说最简单),我添加了一些非捕获组(“(?:”部分 – 感谢VonC向我介绍非捕获组!),所以只捕获包含数字或*字符。
^(?:(\d+)\.)?(?:(\d+)\.)?(\*|\d+)$
非常感谢大家!
我会表示格式为:
“1-3点分隔的组件,每个数字除了最后一个可以是*”
作为一个正则expression式,这是:
^(\d+\.)?(\d+\.)?(\*|\d+)$
[编辑添加:这个解决scheme是一个简明的方法来validation,但有人指出,提取值需要额外的工作。 无论是通过使正则expression式复杂化还是通过处理匹配的组来处理这个问题都是一个问题。
在我的解决scheme中,这些组织捕获了"."
字符。 这可以像使用阿贝里的答案一样使用非捕获组来处理。
此外,即使组件数量less于三个,最右边的组也会捕获最后一个组件,因此,例如,双组件input会导致第一组和最后一组捕获,而中间一个组件未捕获。 我认为这可以由支持的非贪婪组织处理。
在正则expression式之后处理这两个问题的Perl代码可能是这样的:
@version = (); @groups = ($1, $2, $3); foreach (@groups) { next if !defined; s/\.//; push @version, $_; } ($major, $minor, $mod) = (@version, "*", "*");
这并不比“分裂"."
更短"."
]
使用正则expression式,现在你有两个问题。 我会分开点(“。”)的事情,然后确保每个部分是一个通配符或一组数字(正则expression式是完美的现在)。 如果事情是有效的,你只是返回正确的分块。
感谢所有的回应! 这是王牌:)
基于OneByOne的回答(对我来说最简单),我添加了一些非捕获组(“(?:”部分 – 感谢VonC向我介绍非捕获组!),所以只捕获包含数字或*字符。
^(?:(\d+)\.)?(?:(\d+)\.)?(\*|\d+)$
非常感谢大家!
这可能工作:
^(\*|\d+(\.\d+){0,2}(\.\*)?)$
在顶层,“*”是有效版本号的特殊情况。 否则,它以一个数字开始。 然后有零个,一个或两个“.nn”序列,然后是一个可选的“。*”。 这个正则expression式会接受1.2.3。*,在你的应用程序中可能允许也可能不允许。
检索匹配序列的代码,特别是(\.\d+){0,2}
部分,将取决于您的特定正则expression式库。
不知道你在哪个平台上,但在.NET中有System.Version类,它将为你parsing“nnnn”版本号。
我倾向于同意分裂的build议。
我已经在perl中为你的问题创build了一个“testing器”
#!/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"; }
电stream输出:
> 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 ------------------------
我的2美分:我有这种情况:我不得不从string文本parsing版本号。 (我知道这是非常不同的原始问题,但谷歌寻找parsing版本号的正则expression式显示此线程在顶部,所以在这里添加此答案)
所以string文字就像这样:“Service version 1.2.35.564 is running!”
我不得不从这个文字中parsing出1.2.35.564。 从@ajborley得到一个提示,我的正则expression式如下:
(?:(\d+)\.)?(?:(\d+)\.)?(?:(\d+)\.\d+)
一个testing它的小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 }
另一个尝试:
^(((\d+)\.)?(\d+)\.)?(\d+|\*)$
这给出了4,5,6组中的三个部分,但是:它们alignment到右边。 所以4,5或6中的第一个非空值给出版本字段。
- 1.2.3给出1,2,3
- 1.2。*给出1,2,*
- 1.2给出null,1,2
- ***给null,null,*
- 1. *给null,1,*
这应该符合你的规定。 它取决于通配符的位置,是一个嵌套的正则expression式:
^((\*)|([0-9]+(\.((\*)|([0-9]+(\.((\*)|([0-9]+)))?)))?))$
我见过很多答案,但是…我有一个新的答案。 它至less适用于我。 我已经添加了一个新的限制。 版本号无法启动(主要,次要或补丁)与任何零跟随其他。
01.0.0无效1.0.0有效10.0.10有效1.0.0000无效
^(:( 0 \ |?。([1-9] + \ d *)\))+(:( 0 \ |?([1-9] + \ d *)。\))+( (0 |([1-9] + \ d *)))$
它基于前一个。 但是,我看到这个解决scheme更好…对我来说;)
请享用!!!
(?ms)^((?:\d+(?!\.\*)\.)+)(\d+)?(\.\*)?$|^(\d+)\.\*$|^(\*|\d+)$
与你的第一个例子完全一致,拒绝另外四个例子
- 组1:主要或major.minor或'*'
- 第2组如果存在:次要或*
- 第3组如果存在:*
你可以删除'(?ms)'
我用它来表示这个正则expression式通过QuickRex在多行应用
这也匹配1.2.3。*
^(。* |?\ d +(\ d +){0,2}(*))$
我会build议不那么优雅的:
(* | \ d +(\ d +)(*)。?。?)|。\ d + \ d + \ d +)
请记住,正则expression式是贪婪的,所以如果你只是在版本号string内search,而不是在一个更大的文本中,使用^和$来标记你的string的开始和结束。 格雷格的正则expression式似乎工作正常(只是在我的编辑器中快速尝试),但取决于您的库/语言,第一部分仍然可以匹配错误的版本号中的“*”。 也许我错过了一些东西,因为我一年左右没有使用正则expression式。
这应该确保你只能find正确的版本号码:
^(\ * |。?\ d +(\ \ d +)*(\ \ *))$
编辑:实际上格雷格已经添加了他们,甚至改善了他的解决scheme,我太慢了:)
看来很难有一个正则expression式正是你想要的(即只接受你需要的情况,拒绝所有其他的并返回一些组的三个组件)。 我试了一下,想出了这个:
^(\*|(\d+(\.(\d+(\.(\d+|\*))?|\*))?))$
国际海事组织(我没有广泛的testing)这应该工作得很好,作为inputvalidation,但问题是,这个正则expression式不提供检索组件的方式。 为此,你仍然需要做一个分裂的时期。
这个解决scheme并不是一体的,但大多数时候在编程时并不需要。 当然,这取决于你在代码中可能有的其他限制。
^(?:(\d+)\.)?(?:(\d+)\.)?(\*|\d+)$
也许更简洁的一个可能是:
^(?:(\d+)\.){0,2}(\*|\d+)$
然后可以使用*或{2}而不是{0,2}将其严格限制在1.2.3.4.5。
另一个解决scheme:
^[1-9][\d]*(.[1-9][\d]*)*(.\*)?|\*$
指定XSD元素:
<xs:simpleType> <xs:restriction base="xs:string"> <xs:pattern value="[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}(\..*)?"/> </xs:restriction> </xs:simpleType>
我认为这是一个很好的练习 – vparse ,它有一个很小的来源 ,具有一个简单的function:
function parseVersion(v) { var m = v.match(/\d*\.|\d+/g) || []; v = { major: +m[0] || 0, minor: +m[1] || 0, patch: +m[2] || 0, build: +m[3] || 0 }; v.isEmpty = !v.major && !v.minor && !v.patch && !v.build; v.parsed = [v.major, v.minor, v.patch, v.build]; v.text = v.parsed.join('.'); return v; }
我有一个要求search/匹配的版本号,遵循maven惯例,甚至只是一个数字。 但是在任何情况下都没有限定词。 这是奇特的,花了我的时间,然后我想出了这个:
'^[0-9][0-9.]*$'
这确保了版本,
- 以数字开始
- 可以有任何数字的数字
- 只有数字和'。' 被允许
一个缺点是版本甚至可以以'。'结尾。 但是它可以处理无限长的版本(如果你想称之为疯狂版本)
火柴:
- 1.2.3
- 1.09.5
- 3.4.4.5.7.8.8。
- 23.6.209.234.3
如果你对''不满意'。 结局,可能是你可以结合逻辑与endswith