Как мне найти длину строки Unicode в Perl? - PullRequest
12 голосов
/ 25 августа 2009

Страница perldoc для length () говорит мне, что я должен использовать bytes::length(EXPR), чтобы найти строку Unicode в байтах, или страница 10000 * 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";

Вывод этого скрипта, однако, не согласуется с man-страницей:

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

Мне кажется, что length () и bytes :: length () возвращают одинаковые строки ASCII и Unicode. Мой редактор по умолчанию настроен на запись файлов в формате UTF-8, поэтому я считаю, что Perl интерпретирует весь сценарий как Unicode - значит ли это, что length () автоматически обрабатывает строки Unicode правильно?

Редактировать: Смотрите мой комментарий; Мой вопрос не имеет большого смысла, потому что length () не работает "правильно" в приведенном выше примере - он показывает длину строки Unicode в байтах, а не в символах. Резонанс, который я наткнулся на это, касается программы, в которой мне нужно установить заголовок Content-Lenth (в байтах) в HTTP-сообщении. Я читал об Unicode в Perl и ожидал, что мне придется что-то придумать, чтобы все заработало, но когда length () вернул именно то, что мне было нужно, я был в замешательстве! См. Принятый ответ для обзора use utf8, use bytes и no bytes в Perl.

Ответы [ 3 ]

22 голосов
/ 25 августа 2009

Если ваши скрипты закодированы в UTF-8, используйте прагму utf8 . Прагма bytes , с другой стороны, вызовет семантику байтов по длине, даже если строка 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 голосов
/ 25 августа 2009

Цель прагмы bytes состоит в замене функции 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";

Еще один тонкий недостаток в ваших рассуждениях заключается в том, что существует такая вещь, как байты Юникода. Юникод - это перечисление символов. Например, в нем говорится, что U + 24d5 равно & # x24d5 (ЗАКРЫТОЕ ЛАТИНСКОЕ МАЛЕНЬКОЕ ПИСЬМО F); Какой Unicode не указывает, сколько байтов занимает символ. Это оставлено кодировкам. UTF-8 говорит, что он занимает 3 байта, UTF-16 говорит, что он занимает 2 байта, UTF-32 говорит, что он занимает 4 байта и т. Д. Вот сравнение кодировок Unicode . Perl использует UTF-8 для своих строк по умолчанию. UTF-8 обладает тем преимуществом, что он во всех отношениях идентичен ASCII для первых 127 символов.

1 голос
/ 19 марта 2013

Я обнаружил, что можно использовать модуль кодирования, чтобы влиять на работу длины.

, если $ string является строкой в ​​кодировке utf8.

Encode :: _ utf8_on ($ строка); # функция length покажет количество кодовых точек после этого.

Encode :: _ utf8_off ($ строка); # Функция length покажет количество байтов в строке после этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...