2009-08-25 37 views
11

Trang perldoc cho length() cho tôi biết rằng tôi nên sử dụng bytes::length(EXPR) để tìm chuỗi Unicode theo byte hoặc trang bytes lặp lại điều này.Làm cách nào để tìm độ dài của chuỗi Unicode trong Perl?

use bytes; 
$ascii = 'Lorem ipsum dolor sit amet'; 
$unicode = 'Lørëm ípsüm dölör sît åmét'; 

print "ASCII: " . length($ascii) . "\n"; 
print "ASCII bytes: " . bytes::length($ascii) . "\n"; 
print "Unicode: " . length($unicode) . "\n"; 
print "Unicode bytes: " . bytes::length($unicode) . "\n"; 

Kết quả của kịch bản này, tuy nhiên, không đồng ý với manpage:

ASCII: 26 
ASCII bytes: 26 
Unicode: 35 
Unicode bytes: 35 

Dường như với tôi chiều dài() và byte :: length() trả lại tương tự cho cả hai ASCII & chuỗi Unicode . Tôi có biên tập viên của tôi thiết lập để ghi các tập tin như UTF-8 theo mặc định, vì vậy tôi hình Perl là giải thích toàn bộ kịch bản như Unicode-không có nghĩa là chiều dài() tự động xử lý chuỗi Unicode đúng cách?

Chỉnh sửa: Xem nhận xét của tôi; câu hỏi của tôi không có ý nghĩa gì cả, bởi vì length() là không phải hoạt động "đúng" trong ví dụ trên - nó hiển thị độ dài của chuỗi Unicode theo byte, không phải ký tự. Các reson tôi ban đầu vấp qua này là cho một chương trình mà tôi cần phải đặt tiêu đề Content-Lenth (theo byte) trong một tin nhắn HTTP. Tôi đã đọc trên Unicode trong Perl và mong đợi phải làm một số fanciness để làm cho mọi thứ hoạt động, nhưng khi length() trả về chính xác những gì tôi cần ngay lập tức của con dơi, tôi đã nhầm lẫn! Xem câu trả lời được chấp nhận để biết tổng quan về use utf8, use bytesno bytes trong Perl.

+0

Tôi không thấy lý do tại sao bạn nói rằng độ dài() xử lý các chuỗi unicode đúng cách. Trong chiều dài ví dụ của bạn() cho kết quả tương tự như byte :: length(), đó là số byte, không phải số ký tự (mà sẽ là thích hợp). – Inshallah

+0

Nói cách khác, độ dài ($ unicode) diễn giải chuỗi như ASCII, không phải là unicode. – Inshallah

+0

Bạn hoàn toàn chính xác! Tôi đã hoàn toàn bỏ qua thực tế này - trong chương trình của tôi, tôi đang sử dụng length() để đặt tiêu đề Content-Length trong một thông báo HTTP, cần phải theo byte. Sau khi đọc các tài liệu length(), tôi đã mong đợi hàm đó trả về một cái gì đó không chính xác, nhưng thực ra chính xác những gì tôi muốn khi Perl đang ở chế độ 'use bytes': độ dài của chuỗi Unicode theo byte, chứ không phải là ký tự. –

Trả lời

21

Nếu tập lệnh của bạn được mã hóa bằng UTF-8, vui lòng sử dụng utf8 pragma. Mặt khác, bytes pragma sẽ buộc byte ngữ nghĩa dài, ngay cả khi chuỗi là UTF-8. Cả hai đều hoạt động trong phạm vi từ vựng hiện tại.

$ascii = 'Lorem ipsum dolor sit amet'; 
{ 
    use utf8; 
    $unicode = 'Lørëm ípsüm dölör sît åmét'; 
} 
$not_unicode = 'Lørëm ípsüm dölör sît åmét'; 

no bytes; # default, can be omitted 
print "Character semantics:\n"; 

print "ASCII: ", length($ascii), "\n"; 
print "Unicode: ", length($unicode), "\n"; 
print "Not-Unicode: ", length($not_unicode), "\n"; 

print "----\n"; 

use bytes; 
print "Byte semantics:\n"; 

print "ASCII: ", length($ascii), "\n"; 
print "Unicode: ", length($unicode), "\n"; 
print "Not-Unicode: ", length($not_unicode), "\n"; 

đầu ra này:

Character semantics: 
ASCII: 26 
Unicode: 26 
Not-Unicode: 35 
---- 
Byte semantics: 
ASCII: 26 
Unicode: 35 
Not-Unicode: 35 
4

Mục đích của bytes pragma là để thay thế cho length chức năng (và một số chức năng chuỗi liên quan khác) trong phạm vi hiện tại. Vì vậy, mọi cuộc gọi đến length trong chương trình của bạn là một cuộc gọi đến số lengthbytes cung cấp. Điều này phù hợp hơn với những gì bạn đang cố gắng làm:

#!/usr/bin/perl 

use strict; 
use warnings; 

sub bytes($) { 
    use bytes; 
    return length shift; 
} 

my $ascii = "foo"; #really UTF-8, but everything is in the ASCII range 
my $utf8 = "\x{24d5}\x{24de}\x{24de}"; 

print "[$ascii] characters: ", length $ascii, "\n", 
    "[$ascii] bytes  : ", bytes $ascii, "\n", 
    "[$utf8] characters: ", length $utf8, "\n", 
    "[$utf8] bytes  : ", bytes $utf8, "\n"; 

Một lỗ hổng tinh tế khác trong lý do của bạn là có một thứ như Unicode byte. Unicode là một liệt kê các ký tự. Nó nói, ví dụ, U + 24d5 là & # x24d5 (CIRCLED LATIN SMALL LETTER F); Những gì Unicode không chỉ định số byte mà một ký tự chiếm. Đó là để lại cho các mã hóa. UTF-8 cho biết nó chiếm 3 byte, UTF-16 cho biết nó chiếm 2 byte, UTF-32 cho biết phải mất 4 byte, vv Đây là comparison of Unicode encodings. Perl sử dụng UTF-8 cho các chuỗi của nó theo mặc định. UTF-8 có lợi ích giống hệt nhau theo mọi cách đối với ASCII cho 127 ký tự đầu tiên.

1

Tôi thấy rằng có thể sử dụng mô-đun mã hóa để tác động đến độ dài hoạt động của nó.

nếu chuỗi $ là chuỗi được mã hóa utf8.

Mã hóa :: _ utf8_on ($ string); # Hàm chiều dài sẽ hiển thị số điểm mã sau này.

Mã hóa :: _ utf8_off ($ string); # Hàm length sẽ hiển thị số byte trong chuỗi sau này.

Các vấn đề liên quan