2013-03-02 17 views
8

Non riesco a trovare una descrizione di base su come i dati di stringa sono memorizzati in Perl! È come se tutta la documentazione presupponesse che io già lo sapessi per qualche motivo. So di encode(), decode(), e so di poter leggere i byte grezzi in una "stringa" Perl e di emetterli di nuovo senza perl avvitarli. Conosco le modalità aperte. Ho anche capito che Perl deve usare un formato interal per memorizzare stringhe di caratteri e può distinguere tra caratteri e dati binari. Per favore, dove è documentato ???Che diamine è una stringa Perl comunque?

La domanda equivalente è; dato questo perl:

$x = decode($y); 

Decodifica in CHE COSA e da COSA ???

Per quanto posso immaginare ci deve essere un flag sulla struttura dei dati stringa che dice che si tratta di dati di carattere XOR binari (di un certo formato interno che BTW è un superset di Unicode - http://perldoc.perl.org/Encode.html#DESCRIPTION). Ma mi piacerebbe se ciò fosse affermato nei documenti o confermato/screditato qui.

+2

['perldoc perlguts'] (http://perldoc.perl.org/perlguts.html) avrà alcune informazioni. Nota che le stringhe di solito non sono magiche; sembra che siano a volte. –

+0

Grazie Jon, questa è la migliore risposta finora. perlguts sembra divertente.E credimi non credo nella magia, specialmente quando si tratta di Perl. – spinkus

+0

Ho trovato [questo] (http://plosquare.blogspot.in/2009/04/viewing-internal-representation-of.html) anche utile. –

risposta

15

Questa è una grande domanda. Per investigare, possiamo approfondire un po 'usando Devel::Peek per vedere cosa viene effettivamente memorizzato nelle nostre stringhe (o in altre variabili).

primo luogo permette di iniziare con una stringa ASCII

$ perl -MDevel::Peek -E 'Dump "string"' 
SV = PV(0x9688158) at 0x969ac30 
    REFCNT = 1 
    FLAGS = (POK,READONLY,pPOK) 
    PV = 0x969ea20 "string"\0 
    CUR = 6 
    LEN = 12 

Poi possiamo accendere unicode strati IO e fare lo stesso

$ perl -MDevel::Peek -CSAD -E 'Dump "string"' 
SV = PV(0x9eea178) at 0x9efcce0 
    REFCNT = 1 
    FLAGS = (POK,READONLY,pPOK) 
    PV = 0x9f0faf8 "string"\0 
    CUR = 6 
    LEN = 12 

Da lì Proviamo a aggiungere manualmente alcuni caratteri estesi

$ perl -MDevel::Peek -CSAD -e 'Dump "string \x{2665}"' 
SV = PV(0x9be1148) at 0x9bf3c08 
    REFCNT = 1 
    FLAGS = (POK,READONLY,pPOK,UTF8) 
    PV = 0x9bf7178 "string \342\231\245"\0 [UTF8 "string \x{2665}"] 
    CUR = 10 
    LEN = 12 

Da ciò si può chiaramente vedere che Perl l'ha interpretato correttamente come utf8. Il problema è che se non do gli ottetti utilizzando il \x{} sfuggire la rappresentazione sembra più la stringa normale

$ perl -MDevel::Peek -CSAD -E 'Dump "string ♥"' 
SV = PV(0x9143058) at 0x9155cd0 
    REFCNT = 1 
    FLAGS = (POK,READONLY,pPOK) 
    PV = 0x9168af8 "string \342\231\245"\0 
    CUR = 10 
    LEN = 12 

Tutti Perl vede è byte e non ha modo di sapere che loro si intende come un carattere Unicode , a differenza di quando hai inserito gli ottetti sfuggiti sopra. Ora lascia usare decode e vedere cosa succede

$ perl -MDevel::Peek -CSAD -MEncode=decode -E 'Dump decode "utf8", "string ♥"' 
SV = PV(0x8681100) at 0x8683068 
    REFCNT = 1 
    FLAGS = (TEMP,POK,pPOK,UTF8) 
    PV = 0x869dbf0 "string \342\231\245"\0 [UTF8 "string \x{2665}"] 
    CUR = 10 
    LEN = 12 

TADA!, ora puoi vedere che la stringa è correttamente rappresentata internamente corrispondente a ciò che hai inserito quando hai usato l'escape \x{}.

La risposta effettiva è "decodifica" dai byte ai caratteri, ma penso che abbia più senso quando si visualizza l'output Peek.

Infine, è possibile effettuare il Perl si vede il codice sorgente come utf8 tramite utf8 pragma, in questo modo

$ perl -MDevel::Peek -CSAD -Mutf8 -E 'Dump "string ♥"' 
SV = PV(0x8781170) at 0x8793d00 
    REFCNT = 1 
    FLAGS = (POK,READONLY,pPOK,UTF8) 
    PV = 0x87973b8 "string \342\231\245"\0 [UTF8 "string \x{2665}"] 
    CUR = 10 
    LEN = 12 
+0

Wow Grazie! Mi ha dato molto lavoro! – spinkus

+0

@downvoter, cura di commentare? –

-2

Perl può gestire più di una lattina Unicode, quindi è molto flessibile. A volte vuoi interagire con qualcosa che non può, quindi puoi usare la codifica (...) e decodificare (...) gestire quelle trasformazioni. vedi http://perldoc.perl.org/utf8.html

+1

Trasformazioni da e per cosa? Qual è la rappresentazione interna? Questa è la mia domanda. Il tuo dire la rappresentazione interna di un personaggio è un superset di Unicode? Questo è coerente con alcuni dei documenti che ho letto su http://perldoc.perl.org/Encode.html#DESCRIPTION. Ok bene. Allora, come sono archiviati i dati binari in una stringa? – spinkus

+0

Questo in realtà non risponde a nulla che l'OP ha chiesto. – friedo

2

Il formato di stringa interna di Perls dipende dall'implementazione, ma di solito è un super set di UtF-8. Non importa cosa sia perché usi la decodifica e la codifica per convertire stringhe da e verso il formato interno ad altre codifiche.

Decode converte in formato interno perls, codifica convertiti dal formato interno perls.

I dati binari vengono memorizzati internamente allo stesso modo dei caratteri da 0 a 255.

Codifica e decodifica solo conversione tra formati. Ad esempio, la codifica UTF8 significa che ogni carattere sarà solo un ottetto usando perl caratteri da 0 a 255, cioè che la stringa è composta da ottetti UTF8.

3

Risposta breve: E 'un pasticcio
Leggermente più lungo: la differenza non è visibile al programmatore.

Fondamentalmente è necessario ricordare se la stringa contiene byte o caratteri, in cui i caratteri sono codici unicode. Se incontri solo ASCII, la differenza è invisibile, il che è pericoloso.

I dati stessi e la rappresentazione di tali dati sono distinti e non devono essere confusi. Le stringhe sono (concettualmente) una sequenza di codepoint, ma sono rappresentate come una matrice di byte in memoria e rappresentate come una sequenza di byte quando encode d. Se si desidera memorizzare dati binari in una stringa, si reinterpreta il numero di un punto di codice come valore di byte e si limita a codepoint in 0-255.

(ad esempio un file non ha la codifica. Le informazioni contenute in quel file ha qualche codifica (sia esso ASCII, UTF-16 o EBCDIC ad un livello di carattere, e Perl, HTML o .ini ad un livello di applicazione))

Il formato di archiviazione esatto di una stringa è irrilevante, ma è possibile memorizzare numeri interi completi all'interno di una tale stringa:

# this will work if your perl was compiled with large integers 
my $string = chr 2**64; # this is so not unicode 
say ord $string; # 18446744073709551615 

Il formato interno è regolato di conseguenza per accogliere tali valori; le stringhe normali non prenderanno un intero per carattere.

+0

Non vedo molto la tua distinzione in quanto, su questa base, nessun dato ha una codifica: solo le informazioni hanno la codifica. La maggior parte delle persone intende la stessa cosa per * data * e * informazione *, e non ha molto senso parlare di qualcosa senza codifica in quanto non ha scopo o significato. – Borodin

6

Piuttosto come lo stato di stringa/numero fluido delle sue variabili scalari, il formato interno delle stringhe di Perl è variabile e dipende dal contenuto della stringa.

Dai un'occhiata a perluniintro, che dice questo.

Internamente, Perl utilizza attualmente qualunque sia il set di caratteri nativi a otto bit della piattaforma (ad esempio Latin-1), per impostazione predefinita UTF-8, per codificare le stringhe Unicode. In particolare, se tutti i punti di codice nella stringa sono 0xFF o meno, Perl utilizza il set di caratteri nativi a otto bit. In caso contrario, utilizza UTF-8.

Ciò significa che una stringa come "I have £ two" viene memorizzata come (bytes) I have \x{A3} two. (Il cancelletto è U+00A3.) Ora se aggiungo una stringa unicode multi-byte come U+263A - una faccia sorridente - Perl convertirà l'intera stringa in UTF-8 prima di aggiungere il nuovo carattere, dando (byte) I have \xC2\xA3 two\xE2\x98\xBA. La rimozione di quest'ultimo carattere di nuovo lascia la stringa UTF-8 codificata come `I have \xC2\xA3 two.

Ma mi chiedo perché tu debba saperlo. A meno che non si stia scrivendo un'estensione XS in C, il formato interno è trasparente e invisibile all'utente.

+0

Grazie. Sono d'accordo che la codifica di una "stringa" di "caratteri" sia trasparente. Vedo che sequenze di byte e sequenze di caratteri - che Perl tratta in modo diverso, sono entrambi memorizzati nello stesso tipo di dati. Principalmente quello che stavo chiedendo è come Perl ha fatto questo, e ho la risposta. Questo mi è sembrato problematico sin dall'inizio, e le risposte date mostrano che lo è, e quindi vale la pena di sapere :) – spinkus

+0

Perl non ha un tipo di dati che è una "sequenza di byte": una stringa è una sequenza di caratteri. In che modo è "problematico"? – Borodin

+0

"Fondamentalmente è necessario ricordare se la stringa contiene byte o caratteri" - @amon. – spinkus

Problemi correlati