Perl比较运算符和字符串化的“数字”

11

我最近一直在使用Perl,但对于像<,>,>=,=<, ne,gt等在字符串形式的“数字”上如何运作并不是很了解。在这里,“数字”指的是类似于:“1.4.5.6.7.8.0”的东西。

如果我没错的话,以下代码返回true:

if ('1.4.5' > '8.7.8');

因为两者都会被强制转换为true(不是空字符串)。 但是,对于这样的数字,ne,gt等字符串运算符是如何工作的呢?

基本上,我正在尝试比较由以下形式组成的版本号:

1.3.4.0.2
我可以对每个数字进行数值比较,但在此之前,我更想知道字符串比较运算符如何处理这些字符串。
谢谢。

1
"1.4.5.6.7.8.0"不是一个数字。请参阅[perldata](http://perldoc.perl.org/perldata.html)和[Scalar :: Util](http://search.cpan.org/perldoc?Scalar :: Util)的“looks_like_number”。 - ikegami
1
实际上,你说了“number”:“通过‘number’我指的是像‘1.4.5.6.7.8.0’这样的东西。”然后你使用了 «>»,它在每一边都需要一个数字,因此即使你说“numbers”,我的评论也是恰当的。 - ikegami
5个回答

18

首先:请始终使用use warnings。您会立即意识到以下内容:

$ perl -wle 'print 1 unless "1.4.5" > "8.7.8"'
Argument "8.7.8" isn't numeric in numeric gt (>) at -e line 1.
Argument "1.4.5" isn't numeric in numeric gt (>) at -e line 1.

Perl v5.9.0被分发时附带了version模块。而这个模块使得比较版本号变得非常容易:

use warnings;
use version;

my ($small, $large) =  (version->parse('1.4.5'), version->parse('8.7.8'));

print "larger\n"    if $small > $large;
print "smaller\n"   if $small < $large;

8

如果点之间的每个数字长度相同,字符串比较才能正常工作。字符串比较不了解数字,并将开始比较点和数字(因为它们都是字符串中的字符)。

有一个CPAN模块可以完全满足您的要求:Sort::Versions


3
比较字符串时,如果使用数值关系运算符<>等,在Perl中使用use warnings会发出警告。但是,Perl仍会尝试将字符串转换为数字。如果字符串以数字开头,则Perl将使用这些数字进行比较,否则该字符串等同于0。例如,在比较'1.4.5'和'8.7.8'时,效果与比较1.4和8.7相同。
但对于negt等运算符来说,字符串是否由数字或其他字符(包括点号)组成并不重要。因此:
print "greater" if '2.3.4' gt '10.1.2'  # prints 'greater' because '2' > '1' stringwise 
print "greater" if '02.3.4' gt '10.1.2' # prints nothing because '0' < '1' stringwise

因此,您不能使用><等符号,也不能使用gtlt等符号进行版本比较。您必须选择其他方法,例如另一个答案中提出的方法。

2

正如@tent所指出的那样,@SebastianStumpf的解决方案是接近正确的,但并不完全正确,因为:

>perl -Mversion -e 'my @n = ( "1.10", "1.9" ); print "$n[0] is " . ( version->parse($n[0]) > version->parse($n[1]) ? "larger" : "smaller" ) . " than $n[1]\n";'
1.10 is smaller than 1.9

幸运的是,按照版本文档中的提示,这很容易解决:

现在强烈建议在版本号前加上 'v' 以增强清晰度,如果省略将在未来的版本中发出警告。

>perl -Mversion -e 'my @n = ( "1.10", "1.9" ); print "$n[0] is " . ( version->parse("v$n[0]") > version->parse("v$n[1]") ? "larger" : "smaller" ) . " than $n[1]\n";'
1.10 is larger than 1.9

2

我不确定这样做的开销如何,但您可以尝试使用Sort::Naturally。特别是ncmp运算符。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接