2012-03-30 16 views
9

He estado trabajando mucho últimamente con Perl, todavía no sé cómo <,>,>=,=<, ne,gt, etc. en "números" en cadena, por "número" me refiero a algo así como: '1.4 .5.6.7.8.0'operadores de comparación Perl y "números" en cadena

corrígeme si me equivoco, las siguientes declaraciones de verdad:

if ('1.4.5' > '8.7.8'); 

porque ambos serán coaccionados a verdadero (no es una cadena vacía). pero, ¿cómo funcionan los operadores de cadena ne,gt, etc en tales números?

básicamente estoy tratando de comparar los números de versión consistieron en la siguiente forma:

1.3.4.0.2 

puedo hacer una comparación numérica de cada dígito, pero antes, me ranther quieren saber de los operadores de cadena comparar realizar en tales cadenas.

Gracias,

+1

"1.4.5.6.7.8.0" no es un número. Ver [perldata] (http://perldoc.perl.org/perldata.html) y [Scalar :: Util] (http://search.cpan.org/perldoc?Scalar::Util) 's' looks_like_number'. – ikegami

+0

Dije "números" – snoofkin

+1

En realidad, dijo "número": «por" número "me refiero a algo así como:" 1.4.5.6.7.8.0 "». Y luego usaste «'> '», que tiene un * número * en cada lado, por lo que mi comentario es apropiado incluso si dijiste "números". – ikegami

Respuesta

17

Primero: Por favor use warnings todo el tiempo. Se habría dado cuenta lo siguiente a la vez:

$ 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 vino distribuye con version. Y este módulo hace que sea muy fácil comparar los números de versión:

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

Una comparación de cadenas sólo funcionará si todos los números entre los puntos tiene la misma longitud. Una comparación de cadenas no tiene conocimiento de número y comenzará a comparar puntos y dígitos (ya que ambos son caracteres en una cadena).

Hay un módulo CPAN que hace exactamente lo que busca: Sort::Versions

3

Al comparar cadenas utilizando los operadores numéricos de relación <, >, etc., Perl emite una advertencia si use warnings. Sin embargo, Perl aún intentará convertir las cadenas en números. Si la cadena comienza con dígitos, Perl los usará, de lo contrario la cadena equivale a 0. En su ejemplo, comparar '1.4.5' y '8.7.8' tiene el mismo efecto que comparar los números 1.4 y 8.7.

Pero para ne, gt, etc. realmente no importa si sus cadenas consisten en números o cualquier otra cosa (incluidos los puntos). Por lo tanto:

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 

por lo tanto, no se puede usar ni >, <, etc., ni gt, lt, etc., para comparación de versiones, usted tiene que elegir enfoque diferente, como se propone en otras respuestas, por ejemplo.

2

No estoy seguro sobre la sobrecarga de esto, pero puede intentar Sort::Naturally. Y particularmente, el operador ncmp.

2

Como @tent señaló, @ solución de SebastianStumpf está cerca, pero no del todo bien porque:

>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 

Por suerte esto se soluciona fácilmente siguiendo la pista en version's documentation:

La v Principal' 'ahora se recomienda encarecidamente para mayor claridad, y lanzará una advertencia en una versión futura si se omite.

>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 
Cuestiones relacionadas