这是一个很好的问题。为了进行调查,我们可以通过使用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 看到的只是字节,并且无法知道您的意思是它们是 unicode 字符,这与您在上面输入转义八位字节时不同。现在让我们使用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
TADA!,现在您可以看到字符串在内部正确表示,与您使用\x{}
转义时输入的内容匹配。
实际的答案是它是从字节到字符的“解码”,但我认为当你看到 Peek 输出时它更有意义。
最后,您可以使用utf8
pragma 让 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