到底什么是Perl字符串?

spi*_*kus 9 string perl decode

我找不到字符串数据如何存储在Perl中的基本描述!就像所有的文档假设我已经知道这个由于某种原因.我知道encode(),decode(),我知道我可以将原始字节读入Perl"字符串"并再次输出它们而不用Perl搞砸它们.我知道开放模式.我也收集Perl必须使用一些内部格式来存储字符串,并可以区分字符和二进制数据.请记录在哪里???

等效问题是; 鉴于此perl:

$x = decode($y);
Run Code Online (Sandbox Code Playgroud)

解码为WHAT和什么?

据我所知,字符串数据结构上必须有一个标志,表示这是二进制XOR字符数据(某些内部格式,BTW是Unicode的超集 - http://perldoc.perl.org/Encode.html #DESCRIPTION).但如果在文档中说明或在此确认/声名狼借,我会喜欢它.

Joe*_*ger 16

这是一个很好的问题.为了研究,我们可以通过使用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
Run Code Online (Sandbox Code Playgroud)

然后我们可以打开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
Run Code Online (Sandbox Code Playgroud)

从那里让我们尝试手动添加一些宽字符

$ 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
Run Code Online (Sandbox Code Playgroud)

从中您可以清楚地看到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
Run Code Online (Sandbox Code Playgroud)

所有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
Run Code Online (Sandbox Code Playgroud)

TADA !,现在您可以看到字符串在内部正确表示与您在使用\x{}转义时输入的内容相匹配.

实际答案是从字节到字符的"解码",但我认为当你看到Peek输出时更有意义.

最后,您可以使用utf8pragma 使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
Run Code Online (Sandbox Code Playgroud)


Bor*_*din 6

更像是标量变量的流体字符串/数字状态,Perl字符串的内部格式是可变的,取决于字符串的内容.

看看perluniintro,这说明了这一点.

在内部,Perl当前使用平台的本机八位字符集(例如Latin-1),默认为UTF-8,以编码Unicode字符串.具体来说,如果字符串中的所有代码点都是0xFF或更小,则Perl使用本机8位字符集.否则,它使用UTF-8.

这意味着类似的字符串"I have £ two"存储为(字节)I have \x{A3} two.(英镑符号是U+00A3.)现在,如果我追加一个多字节的unicode字符串,例如U+263A- 一个笑脸 - Perl会在追加新字符之前将整个字符串转换为UTF-8,给出(字节)I have \xC2\xA3 two\xE2\x98\xBA.删除最后一个字符会使字符串UTF-8编码为`I have \xC2\xA3 two.

但我想知道为什么你需要知道这一点.除非您在C中编写XS扩展,否则内部格式是透明的,对您来说是不可见的.