Perl сравнивает операторы и строковые «числа» - PullRequest
9 голосов
/ 30 марта 2012

В последнее время я много работал с Perl, но я действительно не знаю, как <,>,>=,=<, ne,gt и т. Д. С строковыми "числами", под "числом" я имею в виду что-то вроде: '1.4.5.6.7.8.0 «

Поправьте меня. Если я ошибаюсь, следующее возвращает true:

if ('1.4.5' > '8.7.8');

потому что оба будут приведены к истине (не пустой строке). но как ne,gt и т. д. строковые операторы работают с такими числами?

В основном я пытаюсь сравнить номера версий в следующей форме:

1.3.4.0.2

Я могу сделать числовое сравнение каждой цифры, но прежде мне хотелось бы узнать о Операторы сравнения строк выполняют для таких строк.

Спасибо,

Ответы [ 5 ]

17 голосов
/ 30 марта 2012

Первый: Пожалуйста, 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 поставляется с версией . И этот модуль позволяет очень легко сравнивать номера версий:

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 голосов
/ 30 марта 2012

Сравнение строк будет работать только в том случае, если каждое число между точками имеет одинаковую длину. Сравнение строк не знает число и начнет сравнивать точки и цифры (так как они оба являются символами в строке).

Есть модуль CPAN, который делает именно то, что вы ищете: Сортировка :: Версии

3 голосов
/ 30 марта 2012

Когда вы сравниваете строки, используя числовые операторы отношений <, > и т. Д., Perl выдает предупреждение, если вы use warnings. Тем не менее, Perl по-прежнему будет пытаться преобразовать строки в числа. Если строка начинается с цифр, Perl будет использовать их, иначе строка будет равна 0. В вашем примере сравнение «1.4.5» и «8.7.8» имеет тот же эффект, что и сравнение чисел 1.4 и 8.7.

Но для ne, gt и т. Д. Действительно не имеет значения, состоят ли ваши строки из чисел или чего-либо еще (включая точки). Поэтому:

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

Следовательно, вы не можете использовать ни >, < и т. Д., Ни gt, lt и т. Д. Для сравнения версий, вы должны выбрать другой подход, как предлагается, например, в других ответах.

2 голосов
/ 13 июля 2016

Как указывал @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 голосов
/ 30 марта 2012

Не уверен в накладных расходах, но вы можете попробовать Sort::Naturally.В частности, оператор ncmp.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...