令我恐惧的是,我刚刚发现它chr不适用于Unicode,尽管它有所帮助.手册页几乎清晰
返回字符集中该NUMBER表示的字符.例如,chr(65)"在ASCII或Unicode中是"A",而chr(0x263a)是Unicode笑脸.
的确,我可以用笑脸打印
perl -e 'print chr(0x263a)'
Run Code Online (Sandbox Code Playgroud)
但事情就像chr(0x00C0)不起作用.我看到我的perl v5.10.1有点古老,但是当我在源代码中粘贴各种奇怪的字母时,一切都很好.
我试着逗之类的东西use utf8和use encoding 'utf8',我还没有试过像有趣的东西use v5.12,并use feature 'unicode_strings'为它们不与我的版本的工作,我与打打闹闹Encode::decode地发现,我不需要解码因为我没有字节数组进行解码.我阅读了比以往更多的文档,并发现了一些有趣的东西,但没有任何帮助.它看起来像是一种Unicode Bug,但没有给出可用的解决方案.而且我不关心整个字符串语义,我需要的只是一个简单的函数.
那么如何将数字转换为由与其对应的单个字符组成的字符串,以便例如real_chr(0xC0) eq 'À'保持?
我得到的第一个答案解释了IO的所有内容,但我仍然不明白为什么
#!/usr/bin/perl -w
use strict;
use utf8;
use encoding 'utf8';
print chr(0x00C0) eq 'À' ? 'eq1' : 'ne1', " - ", chr(0x263a) eq '?' ? 'eq1' : 'ne1', "\n";
print 'À' =~ /\w/ ? "match1" : "no_match1", " - ", chr(0x00C0) =~ /\w/ ? "match2" : "no_match2", "\n";
Run Code Online (Sandbox Code Playgroud)
版画
ne1 - eq1
match1 - no_match2
Run Code Online (Sandbox Code Playgroud)
这意味着手动输入的'À'不同chr(0x00C0).而且,前者是一个单词构成字符(正确!),而后者不是(但应该是!).
ike*_*ami 11
第一,
perl -le'print chr(0x263A);'
Run Code Online (Sandbox Code Playgroud)
马车.Perl甚至会告诉你:
Wide character in print at -e line 1.
Run Code Online (Sandbox Code Playgroud)
这不符合"工作"的条件.因此,虽然他们在如何提供您想要的东西方面存在差异,但以下任何一项都不能满足您的需求:
perl -le'print chr(0x263A);'
perl -le'print chr(0x00C0);'
Run Code Online (Sandbox Code Playgroud)
要正确输出这些Unicode代码点的UTF-8编码,您需要告诉Perl使用UTF-8对Unicode点进行编码.
$ perl -le'use open ":std", ":encoding(UTF-8)"; print chr(0x263A);'
?
$ perl -le'use open ":std", ":encoding(UTF-8)"; print chr(0x00C0);'
À
Run Code Online (Sandbox Code Playgroud)
现在谈到"为什么".
文件句柄只能传输字节,所以除非你另外告诉它,否则Perl文件处理期望字节.这意味着您提供的字符串print不能包含除字节之外的任何内容,换句话说,它不能包含超过255的字符.输出正是您提供的内容:
$ perl -e'print map chr, 0x00, 0x65, 0xC0, 0xF0' | od -t x1
0000000 00 65 c0 f0
0000004
Run Code Online (Sandbox Code Playgroud)
这很有用.这与你想要的不同,但这并没有错.如果你想要不同的东西,你只需要告诉Perl你想要什么.
通过添加一个:encoding图层,句柄现在需要一串Unicode字符,或者我称之为"text".该层告诉Perl如何将文本转换为字节.
$ perl -e'
use open ":std", ":encoding(UTF-8)";
print map chr, 0x00, 0x65, 0xC0, 0xF0, 0x263a;
' | od -t x1
0000000 00 65 c3 80 c3 b0 e2 98 ba
0000011
Run Code Online (Sandbox Code Playgroud)
您chr不知道或不关心Unicode的权利.如同length,substr,ord和reverse,chr实现了一个基本的字符串函数,而不是一个Unicode功能.这并不意味着它不能用于处理文本字符串.正如您所看到的,问题不chr在于您在构建它之后对字符串所做的事情.
字符是字符串的元素,字符是数字.这意味着字符串只是一系列数字.无论您将这些数字视为Unicode代码点(文本),打包的IP地址还是温度测量都完全取决于您以及传递字符串的函数.
下面是一些运算符的示例,它们为它们作为操作数接收的字符串赋值:
m// 需要一串Unicode代码点.connect期望一个表示sockaddr_in结构的字节序列.print使用句柄而不:encoding期望一个字节序列.print:encoding期望一系列Unicode代码点的句柄.那么如何将数字转换为由与其对应的单个字符组成的字符串,以便例如real_chr(0xC0)eq'À'成立?
chr(0xC0) eq 'À'确实坚持.您是否记得告诉Perl使用UTF-8编码您的源代码use utf8;?如果你没有告诉Perl,Perl实际上在RHS上看到了一个双字符串.
关于你添加的问题:
这个encodingpragma 有问题.我建议不要使用它.相反,使用
use open ':std', ':encoding(UTF-8)';
Run Code Online (Sandbox Code Playgroud)
这将解决其中一个问题.你遇到的另一个问题是
chr(0x00C0) =~ /\w/
Run Code Online (Sandbox Code Playgroud)
这是一个已知的错误,由于向后兼容性原因故意被破坏.也就是说,除非您按如下方式请求更新版本的语言:
use 5.014; # use 5.012; *might* suffice.
Run Code Online (Sandbox Code Playgroud)
一种可以追溯到5.8的解决方法:
my $x = chr(0x00C0);
utf8::upgrade($x);
$x =~ /\w/
Run Code Online (Sandbox Code Playgroud)