Perl版本号排序顺序反转:为何结果不符合预期?
Perl版本号排序异常:15.8排在15.8.1之后的原因及解决方法
嘿,这个问题的根源其实是Perl version模块对不同格式版本号的解析规则差异,咱们来一步步搞清楚:
为什么排序结果不符合预期?
当你用version->parse()解析版本号时,模块会根据输入字符串的格式自动选择解析方式:
- 对于
15.8这种只有两个部分的版本号,parse会把它当成十进制版本(类似浮点数的表示),内部会转换成v15.800.0(可以理解为把小数点后的8当成千分位,即8/1000,对应版本组件是15、800、0)。 - 对于
15.8.1这种三个部分的点分版本号,parse会按点分十进制版本解析,内部表示为v15.8.1。
当这两个版本比较时,v15.800.0显然比v15.8.1大(第二个组件800 > 8),所以cmp操作返回1,意味着$a(15.8)比$b(15.8.1)大,排序后自然会把15.8.1放在前面,15.8放在后面,和你的预期相反。
你可以用这段代码验证内部表示:
use version; my $v1 = version->parse('15.8'); my $v2 = version->parse('15.8.1'); print "$v1\n$v2\n";
输出会是:
v15.800.0 v15.8.1
怎么解决这个问题?
要让版本号按照你预期的点分规则排序,你需要强制version模块对所有输入都使用点分十进制版本的解析逻辑,推荐用version->declare()替代version->parse():
修改后的排序代码:
chomp(my @versions = <>); my @sorted_versions = sort { version->declare($a) cmp version->declare($b) } @versions; print "$_\n" for @sorted_versions;
version->declare()会强制把所有输入都解析为点分十进制版本:
version->declare('15.8')会被解析为v15.8.0version->declare('15.8.1')会被解析为v15.8.1
这时再比较,v15.8.0 < v15.8.1,排序结果就会是15.8在前,15.8.1在后,符合你的预期。
另外,你也可以提前统一版本号格式,比如把所有x.y格式的版本号补全为x.y.0,再用parse解析,也能达到同样的效果。
内容的提问来源于stack exchange,提问作者Jim
相关产品推荐
相关产品推荐

