如何在Perl中找到Unicode字符串的长度?

时间:2009-08-25 07:20:06

标签: perl unicode utf-8

length()perldoc页面告诉我,我应该使用bytes::length(EXPR)以字节为单位查找Unicode字符串,或者bytes页面回应此信息。

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

在我看来,length()和bytes :: length()对于ASCII和&都返回相同的值。 Unicode字符串。我的编辑器设置为默认情况下将文件写为UTF-8,所以我认为Perl将整个脚本解释为Unicode,这意味着length()会自动正确处理Unicode字符串吗?

修改:查看我的评论;我的问题并没有多大意义,因为在上面的例子中,length()正常工作 - 它以字节为单位显示Unicode字符串的长度,而不是字符。我最初偶然发现的共鸣是一个程序,我需要在HTTP消息中设置Content-Lenth标头(以字节为单位)。我已经阅读了Perl中的Unicode,并且期望必须做一些有意义的工作,但是当length()完全返回我需要的蝙蝠时,我很困惑!有关Perl中use utf8use bytesno bytes的概述,请参阅接受的答案。

3 个答案:

答案 0 :(得分:22)

如果您的脚本是以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

答案 1 :(得分: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(CIRCLED LATIN SMALL LETTER F); Unicode没有指定字符占用的字节数。这留给了编码。 UTF-8表示它占用3个字节,UTF-16表示占用2个字节,UTF-32表示需要4个字节,等等。这是comparison of Unicode encodings。 Perl默认使用UTF-8作为字符串。对于前127个字符,UTF-8具有与ASCII相同的各种优点。

答案 2 :(得分:1)

我发现可以使用Encode模块来影响长度的工作方式。

如果$ string是utf8编码的字符串。

编码:: _ utf8_on($字符串); #length函数将显示此后的代码点数。

编码:: _ utf8_off($字符串); #length函数将在此后显示字符串中的字节数。