2012-03-30 13 views
9

Tôi đã làm việc gần đây với perl, tôi vẫn chưa biết cách <,>,>=,=<, ne,gt, v.v. trên "số" được xâu chuỗi, bằng "số" nghĩa là: '1.4 .5.6.7.8.0'Perl so sánh toán tử và "số"

chính xác cho tôi Nếu tôi sai, lợi nhuận sau đúng:

if ('1.4.5' > '8.7.8'); 

vì cả hai sẽ bị cưỡng chế đúng (không phải là một chuỗi rỗng). nhưng, làm cách nào để ne,gt, v.v ... hoạt động trên các số như vậy?

về cơ bản tôi đang cố gắng để so sánh số phiên bản bao gồm các hình thức sau đây:

1.3.4.0.2 

tôi có thể làm một so sánh số của mỗi chữ số, nhưng trước đây, tôi ranther muốn biết các nhà khai thác chuỗi so sánh thực hiện trên các chuỗi như vậy.

Cảm ơn,

+1

"1.4.5.6.7.8.0" không phải là số. Xem [perldata] (http://perldoc.perl.org/perldata.html) và "look_like_number' của [Scalar :: Util] (http://search.cpan.org/perldoc?Scalar::Util). – ikegami

+0

Tôi đã nói "số" – snoofkin

+1

Thực ra, bạn đã nói "số": «theo" số "Tôi có nghĩa là một cái gì đó như: '1.4.5.6.7.8.0'». Và sau đó bạn sử dụng «'> '», có một * số * ở mỗi bên, vì vậy nhận xét của tôi là thích hợp ngay cả khi bạn nói "số". – ikegami

Trả lời

17

Đầu tiên: Xin use warnings tất cả các thời gian. Bạn sẽ nhận ra những điều sau đây cùng một lúc:

$ 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 được phân phối với version. Và module này làm cho nó rất dễ dàng để so sánh số phiên bả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

So sánh chuỗi sẽ chỉ hoạt động nếu mọi số giữa các dấu chấm có cùng độ dài. So sánh chuỗi không có kiến ​​thức về số số và sẽ bắt đầu so sánh các dấu chấm và chữ số (vì chúng là cả hai ký tự trong một chuỗi).

Có một module CPAN mà thực hiện chính xác những gì bạn đang tìm kiếm: Sort::Versions

3

Khi bạn so sánh chuỗi sử dụng số nhà khai thác mối quan hệ <, > vv, Perl đưa ra một cảnh báo nếu bạn use warnings. Tuy nhiên, Perl vẫn sẽ cố gắng chuyển đổi các chuỗi thành số. Nếu chuỗi bắt đầu bằng các chữ số, Perl sẽ sử dụng các số này, nếu không thì chuỗi tương đương với 0. Trong ví dụ của bạn so sánh '1.4.5' và '8.7.8' có cùng tác dụng như so sánh số 1,4 và 8,7.

Nhưng đối với ne, gt, v.v ... thực sự không quan trọng nếu chuỗi của bạn có chứa số hay bất kỳ thứ gì khác (bao gồm dấu chấm). Do đó:

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 

Vì vậy, bạn không thể sử dụng không >, < vv cũng không gt, lt, vv cho phiên bản so sánh, các bạn phải chọn cách tiếp cận khác nhau, như đề xuất trong câu trả lời khác, ví dụ.

2

Không chắc chắn về chi phí này, nhưng bạn có thể thử Sort::Naturally. Và đặc biệt, toán tử ncmp.

2

Như @tent chỉ ra, @ giải pháp SebastianStumpf là gần, nhưng không hoàn toàn đúng vì:

>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 

May mắn này có thể dễ dàng giải quyết sau đây gợi ý trong version's documentation:

Các đầu 'v 'hiện được khuyến khích mạnh mẽ để rõ ràng và sẽ ném cảnh báo trong bản phát hành trong tương lai nếu bị bỏ qua.

>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