2009-08-18 4 views
2

Ich versuche, hexadezimale Darstellungen von Unicode-Zeichen in die Zeichen zu konvertieren, die sie darstellen. Das folgende Beispiel funktioniert gut:Wie kann ich ein Unicode-Zeichen aus seinen Bytes erstellen, wenn sie in verschiedenen Variablen in Perl gespeichert sind?

#!/usr/bin/perl 

use Encode qw(encode decode); 
binmode(STDOUT, ':encoding(utf-8)'); 

my $encoded = encode('utf8', "\x{e382}\x{af}"); 
eval { $encoded = decode('utf8', $encoded, Encode::FB_CROAK); 1 } 
or print("coaked\n"); 

print "$encoded\n"; 

Die Hexadezimalziffern sind jedoch in 3 Variablen gespeichert.

Also, wenn ich ersetzen die Codierfreigabeleitung mit diesem:

my $encoded = encode('utf8', "\x{${byte1}${byte2}}\x{${byte3}}"); 

wo

my $byte1 = "e3"; my $byte2 = "82"; my $byte3 = "af"; 

Es schlägt fehl, da es die \ x sofort und sieht das $ -Zeichen und {als Zeichen zu bewerten versucht.

Wer weiß, wie man das umgehen kann.

Antwort

11

Statt

my $encoded = encode('utf8', "\x{${byte1}${byte2}}\x{${byte3}}"); 

können Sie verwenden

my $encoded = encode('utf8', chr(hex($byte1 . $byte2)) . chr(hex($byte3))); 

hex() von hexadezimal umwandelt und chr() gibt den Unicode-Zeichen für einen Codepunkt gegeben.

[Edit:]

nicht zu Ihrer Frage, aber ich bemerkt, dass Sie utf-8 und utf8 in Ihrem Programm mischen. Ich weiß nicht, ob das ein Tippfehler ist, aber Sie sollten eine Ware sein, dass diese nicht die gleichen Dinge in Perl sind:
utf-8 (mit Bindestrich, Groß- und Kleinschreibung unempfindlich) ist, was der UTF-8-Standard sagt, während utf8 (kein Bindestrich, auch ohne Berücksichtigung der Groß-/Kleinschreibung) ist Perls interne Kodierung, die lockerer definiert ist (es erlaubt Codepunkte, die keine gültigen Unicode-Codepoints sind). Im Allgemeinen sollten Sie bei utf-8 bleiben (perlunifaq hat die Details).

+1

Danke! Das ist was ich brauchte. – Tom

6

Trendel Antwort scheint ziemlich gut, aber Encode::Escape bietet eine alternative Lösung:

use Encode::Escape::Unicode; 

my $hex = '263a'; 
my $escaped = "\\x{" . $hex . "}\n"; 
print encode 'utf8', decode 'unicode-escape', $escaped; 
+1

Danke funktioniert auch! – Tom

0

Zunächst einmal ernsthaft darüber nachdenken, warum Sie mit drei Variablen endete, $ byte1, $ byte2, $ byte3, die jeweils einen Halte Byte Daten, als eine zweistellige Zeichenfolge, in Hexadezimal. Dieser Teil Ihres Programms scheint aufgrund einer schlechten Design-Entscheidung weiter oben schwierig zu sein. Beheben Sie diese schlechte Entscheidung, und dieser Teil des Codes wird natürlich ausfallen.

aber sagen, dass, was Sie tun wollen, glaube ich, ist dies:


my $byte1 = "e3"; my $byte2 = "82"; my $byte3 = "af"; 
my $str = chr(hex($byte1 . $byte2)) . chr(hex($byte3)) 

Die Codierung Zeug ist ein roter Hering; Sie sollten sich keine Sorgen über Codierungen in der Mitte Ihres Programms machen, nur wenn Sie IO durchführen.

Ich gehe davon aus, dass Sie eine zwei Zeichenfolge, U + E382, gefolgt von U + AF, erhalten möchten. Das hast du eigentlich verlangt.Da es jedoch kein U + E382 gibt, ist es wahrscheinlich nicht das, was Sie eigentlich wollten, da es in der Mitte des privaten Bereichs ist. Bitte versuchen Sie die Frage neu zu formulieren? Stellen Sie sich vielleicht eine grundlegendere Frage und beschreiben Sie, was Sie erreichen möchten, und wie Sie es dann versuchen werden?

+0

Da gibt es 3 Variablen, denn so kommen die Daten von Latex zu mir. Das kann nicht geändert werden. Dieses Programm liest ein und gibt dann sofort das Ergebnis aus, daher die Notwendigkeit der Codierung. Die Lösungen, die andere vorher gegeben haben, waren genau das, was benötigt wurde. – Tom