2009-08-25 57 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); #长度函数将在此之后显示字符串中的字节数。

相关问题