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

Dre*_*ens 12 unicode perl utf-8

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

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";
Run Code Online (Sandbox Code Playgroud)

但是,此脚本的输出不同于该联机帮助页:

ASCII: 26
ASCII bytes: 26
Unicode: 35
Unicode bytes: 35
Run Code Online (Sandbox Code Playgroud)

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

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

Ins*_*lah 22

如果您的脚本以UTF-8编码,请使用utf8编译指示.另一方面,字节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";
Run Code Online (Sandbox Code Playgroud)

这输出:

Character semantics:
ASCII: 26
Unicode: 26
Not-Unicode: 35
----
Byte semantics:
ASCII: 26
Unicode: 35
Not-Unicode: 35
Run Code Online (Sandbox Code Playgroud)


Cha*_*ens 6

该编译指示的目的bytes是替换length当前作用域中的函数(以及其他几个与字符串相关的函数)。因此,程序中的每次调用都是对所提供的length的调用。这更符合您想要做的事情:lengthbytes

#!/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";
Run Code Online (Sandbox Code Playgroud)

您的推理中的另一个微妙缺陷是存在 Unicode 字节之类的东西。Unicode 是字符的枚举。例如,它表示 U+24d5 是 ⓕ(带圆圈的拉丁文小写字母 F);Unicode并没有规定一个字符占用多少字节。这就留给了编码。UTF-8表示占用3个字节,UTF-16表示占用2个字节,UTF-32表示占用4个字节等等。这里是Unicode编码的比较。Perl 默认使用 UTF-8 作为其字符串。UTF-8 的优点是前 127 个字符在各方面都与 ASCII 相同。