Cra*_*lus 5 string perl utf-8 character-encoding
在下面的:
my $string = "Can you \x{FB01}nd my r\x{E9}sum\x{E9}?\n";
该x{FB01}和x{E9}是代码点.并且代码点通过编码方案编码为一系列八位字节.
所以è具有代码点的字符\x{FB01}是字符串的一部分$string.但这是如何工作的?是所有的人物在这句话(包括ASCII的)通过编码UTF-8?
如果是,为什么我会得到以下行为?
my $str = "Some arbitrary string\n";
if(Encode::is_utf8($str)) {
print "YES str IS UTF8!\n";
}
else {
print "NO str IT IS NOT UTF8\n";
}
Run Code Online (Sandbox Code Playgroud)
这打印"NO str IT IS NOT UTF8\n"
另外Encode::is_utf8($string)返回true.
以什么方式$string和$str不同而一个被考虑UTF-8而另一个没有?
而且无论如何编码是$str什么?ASCII?这是默认设置Perl吗?
在C中,字符串是八位字节的集合,但Perl有两种字符串存储格式:
因此,您无需对代码点进行编码即可将其存储在字符串中.
my $s = "\x{2660}\x{2661}";
say length $s; # 2
say sprintf '%X', ord substr($s, 0, 1); # 2660
say sprintf '%X', ord substr($s, 1, 1); # 2661
Run Code Online (Sandbox Code Playgroud)
(在内部,UTF-8的扩展名为"utf8"用于存储72位字符串.除了意识到性能影响之外,这不是你应该知道的事情,但是有些错误暴露了这个事实. )
编码is_utf8报告标量包含的字符串类型.除了调试我之前提到的错误之外,它是一个绝对没用的功能.
"abc"(或者是OP中的字符串$str)的值,因此Perl使用更高效的8位(UTF8 = 0)字符串格式."\x{2660}\x{2661}"(或OP中的字符串$string)的值,因此Perl使用72位(UTF8 = 1)字符串格式.无论是存储在浮点数,有符号整数还是无符号整数中,零都为零.类似地,字符串的存储格式不传达有关字符串值的信息.
事实上,Perl将随意在两种格式之间切换.例如,如果您连接$string使用$str,你会得到在72位格式的字符串.
你可以改变与内建的字符串的存储格式utf8::downgrade和utf8::upgrade,你应该永远需要解决的错误.
utf8::downgrade($s); # Switch to strings of 8-bit values (UTF8=0).
utf8::upgrade($s); # Switch to strings of 72-bit values (UTF8=1).
Run Code Online (Sandbox Code Playgroud)
您可以使用Devel :: Peek查看效果.
>perl -MDevel::Peek -e"$s=chr(0x80); utf8::downgrade($s); Dump($s);"
SV = PV(0x7b8a74) at 0x4a84c4
REFCNT = 1
FLAGS = (POK,pPOK)
PV = 0x7bab9c "\200"\0
CUR = 1
LEN = 12
>perl -MDevel::Peek -e"$s=chr(0x80); utf8::upgrade($s); Dump($s);"
SV = PV(0x558a6c) at 0x1cc843c
REFCNT = 1
FLAGS = (POK,pPOK,UTF8)
PV = 0x55ab94 "\302\200"\0 [UTF8 "\x{80}"]
CUR = 2
LEN = 12
Run Code Online (Sandbox Code Playgroud)
\ x {FB01}和\ x {E9}是代码点.
不安静,大括号内的数值是代码点.整个\ x表达式只是一个字符的表示法.字符有几种符号,大多数以反斜杠开头,但常见的是简单的字符串文字.你不妨写一下:
use utf8;
my $string = "Can you ?nd my résumé?\n";
# ? ? ?
Run Code Online (Sandbox Code Playgroud)
并且代码点通过编码方案编码为一系列八位字节.
是的,但到目前为止,你的字符串是一串字符,而不是八位字节的缓冲区.
但这是如何工作的?
字符串由字符组成.这只是Perl的模型.作为程序员,你应该在这个级别处理它.
当然,计算机不能,而内部数据结构必须具有某种形式的内部编码.由于"Perl不能保守秘密",所以会产生太多混乱,细节偶尔会泄露出来.
这句话中的所有字符(包括ASCII字符)都是通过UTF-8编码的吗?
不,内部编码是松散的UTF8(没有破折号).它没有UTF-8(又名UTF-8-strict)的一些限制.
编码:: is_utf8
...是一个内部功能,并清楚地标记为这样.你作为程序员不应该偷看.但既然你想要偷看,没有人可以阻止你.Devel :: Peek :: Dump是一个更好的工具,可以进入内部.
阅读http://p3rl.org/UNI,了解Perl中的编码主题.