これは素晴らしい質問です。調査するために、 Devel :: Peekを使用して、文字列(または他の変数)に実際に何が格納されているかを確認することで、もう少し深く掘り下げることができます。
まず、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
次に、Unicode IOレイヤーをオンにして、同じことを行うことができます
$ 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
そこから、いくつかのワイド文字を手動で追加してみましょう
$ 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
このことから、Perlがこれをutf8として正しく解釈していることがはっきりとわかります。問題は、エスケープを使用してオクテットを指定しない場合\x{}
、表現が通常の文字列のように見えることです。
$ 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
上記のエスケープされたオクテットを入力したときとは異なり、Perlが認識するのはバイトだけであり、それらがユニコード文字であることを意味することを知る方法はありません。ではdecode
、何が起こるかを使って見てみましょう
$ 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
\x{}
TADA !、これで、エスケープを使用したときに入力したものと一致する文字列が内部的に正しく表現されていることがわかります。
実際の答えは、バイトから文字への「デコード」ですが、Peekの出力を見るともっと理にかなっていると思います。
utf8
最後に、プラグマを使用して、Perlにソースコードをutf8として認識させることができます。
$ 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