2009-08-25 58 views
11

length()perldoc頁面告訴我,我應該使用bytes::length(EXPR)來查找以字節爲單位的Unicode字符串,或者bytes頁與此相呼應。如何在Perl中查找Unicode字符串的長度?

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"; 

這個腳本的輸出,但是,與聯機幫助不同意:

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

在我看來,長度()和字節長度::()返回兩個ASCII & Unicode字符串相同。默認情況下,我的編輯器設置爲將文件編寫爲UTF-8,所以我認爲Perl會將整個腳本解釋爲Unicode,那麼意味着length()會自動正確處理Unicode字符串?

編輯:查看我的評論;我的問題並沒有太大意義,因爲在上面的例子中,length()是而不是「正常」工作 - 它顯示的是Unicode字符串的長度(以字節爲單位),而不是字符。我最初偶然發現的這個共振是一個程序,我需要在HTTP消息中設置Content-Lenth標頭(以字節爲單位)。我已經閱讀了Perl中的Unicode,並期望不得不做一些事情來使事情發揮作用,但當length()正好返回我需要的蝙蝠時,我很困惑!在Perl中查看use utf8,use bytesno bytes的概述。

+0

我不明白你爲什麼說length()正確處理unicode字符串。在你的例子中,length()給出了與bytes :: length()相同的結果,即字節數,而不是字符數(這是正確的)。 – Inshallah 2009-08-25 07:26:59

+0

換句話說,length($ unicode)將該字符串解釋爲ASCII,而不是unicode。 – Inshallah 2009-08-25 07:28:41

+0

你絕對正確!我完全忽略了這個事實 - 在我的程序中,我使用length()在HTTP消息中設置Content-Length頭,這需要以字節爲單位。在閱讀length()文檔後,我期待該函數返回不正確的東西,但實際上,當Perl處於「use bytes」模式時,它正是我想要的:Unicode字符串的長度(以字節爲單位),而不是字符。 – 2009-08-25 15:47:09

回答

21

如果您的腳本使用UTF-8編碼,請使用utf8 pragma。另一方面,bytes pragma將強制字節語義的長度,即使字符串是UTF-8。兩者都在當前的詞彙範圍內工作。

$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"; 

此輸出:

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

bytes pragma的目的是要取代當前範圍的length函數(和其他幾個串相關的功能)。因此,在您的程序中撥打length的每個電話都是致電length,即bytes提供的電話。這更符合你想要做的事情:

#!/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"; 

你的推理的另一個細微的缺陷是,有這樣的事情,如Unicode字節。 Unicode是字符的枚舉。它說,例如,U + 24d5是&#x24d5(循環拉丁語小寫字母F); Unicode不指定字符佔用多少字節。這留給編碼。 UTF-8表示佔用3個字節,UTF-16表示佔用2個字節,UTF-32表示佔用4個字節等。這裏是comparison of Unicode encodings。 Perl默認使用UTF-8作爲其字符串。對於前127個字符,UTF-8具有與ASCII相同的優點。

1

我發現可以使用編碼模塊來影響長度的工作方式。

如果$ string是utf8編碼的字符串。

Encode :: _ utf8_on($ string); #長度函數將顯示此後的代碼點數。

Encode :: _ utf8_off($ string); #長度函數將在此之後顯示字符串中的字節數。

相關問題