无法通过从 bash 调用 perl oneliner 来比较两个版本字符串

Cannot compare two version string by calling perl oneliner from bash

我想要一个 bash 函数,如果版本号之间的一次比较结果为真,则为 return 0,如果为假,则为 return 1,所以这就是我所做的:

$ perl -e "exit(!(0.9.8.8 < 0.9.10.0))"
$ echo $?
1

但它不起作用,因为如果我更改比较符号,退出代码是相同的:

$ perl -e "exit(!(0.9.8.8 > 0.9.10.0))"
$ echo $?
1

这个简单的代码适用于浮点数但不适用于版本号,我怎样才能让我的代码适用于版本号?

0.1.2.3 这样的 Perl 文字被解释为 vstrings 并且具有与之相关的魔法:

A literal of the form v1.20.300.4000 is parsed as a string composed of characters with the specified ordinals. This form, known as v-strings, provides an alternative, more readable way to construct strings, rather than use the somewhat less readable interpolation form "\x{1}\x{14}\x{12c}\x{fa0}". This is useful for representing Unicode strings, and for comparing version "numbers" using the string comparison operators, cmp, gt, lt etc. If there are two or more dots in the literal, the leading v may be omitted.

因此,当您比较 0.9.8.8 < 0.9.10.0 时,您正在比较小于 vstrings 的数字,这将导致警告,例如(如果您启用 warnings):

Argument "[=10=]^I\n[=10=]" isn't numeric in numeric lt (<) at -e line 1.

您应该对 vstrings 使用字符串比较, 有关详细信息,请参阅 this blog post

但是,最好使用version模块来比较版本。

根据 documentation:

If you need to compare version numbers, but can't be sure whether they are expressed as numbers, strings, v-strings or version objects, then you should use version.pm to parse them all into objects for comparison.
[...]
Version objects overload the cmp and <=> operators. Perl automatically generates all of the other comparison operators based on those two so all the normal logical comparisons will work. This may give surprising results:

$v1 = version->parse("v0.97.0");
$bool = $v1 > 0.96; # FALSE since 0.96 is v0.960.0

Always comparing to a version object will help avoid surprises.

所以你可以这样做:

perl -Mversion -e 'exit !(version->parse("0.9.8.8")<version->parse("0.9.10.0"))'