2009-08-25 16 views
11

La pagina perldoc per length() mi dice che dovrei usare bytes::length(EXPR) per trovare una stringa Unicode in byte, oppure la pagina bytes echeggia questo.Come trovo la lunghezza di una stringa Unicode in Perl?

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

L'output di questo script, però, non è d'accordo con la pagina di manuale:

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

Mi sembra di lunghezza() e byte :: lunghezza() restituiscono lo stesso per entrambe le ASCII & stringhe Unicode . Il mio editore è impostato per scrivere file come UTF-8 di default, quindi immagino che Perl interpreti l'intero script come Unicode, cioè che length() gestisce automaticamente le stringhe Unicode in modo corretto?

Modifica: Vedere il mio commento; la mia domanda non ha molto senso, perché length() è non che funziona "correttamente" nell'esempio precedente - mostra la lunghezza della stringa Unicode in byte, non caratteri. Il reson che ho originariamente imbattuto in questo è per un programma in cui ho bisogno di impostare l'intestazione Content-Lenth (in byte) in un messaggio HTTP. Avevo letto su Unicode in Perl e mi aspettavo di dover fare un po 'di fanciness per far funzionare le cose, ma quando length() ha restituito esattamente quello di cui avevo bisogno a destra del pipistrello, ero confuso! Vedere la risposta accettata per una panoramica di use utf8, use bytes e no bytes in Perl.

+0

Non vedo perché dici che length() gestisce correttamente le stringhe Unicode. Nell'esempio length() restituisce lo stesso risultato di bytes :: length(), ovvero il numero di byte, non il numero di caratteri (che sarebbe corretto). – Inshallah

+0

In altre parole, length ($ unicode) interpreta la stringa come ASCII, non come unicode. – Inshallah

+0

Hai assolutamente ragione! Mi ero completamente dimenticato di questo fatto: nel mio programma, sto usando length() per impostare l'intestazione Content-Length in un messaggio HTTP, che deve essere in byte. Dopo aver letto i documenti length(), mi aspettavo che quella funzione restituisse qualcosa di non corretto, ma in realtà è esattamente ciò che voglio quando Perl è in modalità 'use bytes ': la lunghezza della stringa Unicode in byte, piuttosto che caratteri. –

risposta

21

Se gli script sono codificati in UTF-8, utilizzare utf8 pragma. Il bytes pragma d'altra parte imporrà la semantica dei byte su lunghezza, anche se la stringa è UTF-8. Entrambi funzionano nell'attuale ambito lessicale.

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

This uscite:

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

Scopo della bytes pragma è quello di sostituire la funzione length (e diverse altre funzioni connesse ad arco) nell'ambito corrente. Pertanto, ogni chiamata a length nel tuo programma è una chiamata allo length fornita da bytes. Questo è più in linea con quello che stavi cercando di fare:

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

Un altro sottile falla nel tuo ragionamento è che c'è una cosa come byte Unicode. Unicode è un'enumerazione di caratteri. Ad esempio, dice che U + 24d5 è & # x24d5 (LETTER FACOLORE LETRO F); Quale Unicode non specifica quanti byte occupa un personaggio. Questo è lasciato alle codifiche. UTF-8 dice che occupa 3 byte, UTF-16 dice che occupa 2 byte, UTF-32 dice che ci vogliono 4 byte, ecc. Ecco comparison of Unicode encodings. Perl utilizza UTF-8 per le sue stringhe per impostazione predefinita. UTF-8 ha il vantaggio di essere identico in tutti i modi a ASCII per i primi 127 caratteri.

1

Ho scoperto che è possibile utilizzare il modulo Encode per influenzare il modo in cui funziona la lunghezza.

se $ stringa è una stringa codificata utf8.

Codifica :: _ utf8_on ($ stringa); # la funzione lunghezza mostrerà il numero di punti codice dopo questo.

Encode :: _ utf8_off ($ string); # la funzione length mostrerà il numero di byte nella stringa dopo questo.

Problemi correlati