2017-02-11 38 views
6

以下脚本被编码以UTF-8:为什么在用“使用utf8”的UTF-8编码的Perl脚本中不能识别变音符号?

use utf8; 

$fuer = pack('H*', '66c3bc72'); 

$fuer =~ s/ü/!!!/; 

print $fuer; 

s///ü存储在脚本c3 bc,如下面的xxd十六进制转储节目。

0000000: 75 73 65 20 75 74 66 38 3b 0a 0a 24 66 75 65 72 use utf8;..$fuer 
0000010: 20 3d 20 70 61 63 6b 28 27 48 2a 27 2c 20 27 36 = pack('H*', '6 
0000020: 36 63 33 62 63 37 32 27 29 3b 0a 0a 24 66 75 65 6c3bc72');..$fue 
0000030: 72 20 3d 7e 20 73 2f c3 bc 2f 21 21 21 2f 3b 0a r =~ s/../!!!/;. 
0000040: 0a 70 72 69 6e 74 20 24 66 75 65 72 3b 0a  .print $fuer;. 

c3 bcü的UTF-8表示。

因为脚本是UTF-8编码和我use荷兰国际集团utf8,我期待的脚本来代替für可变$fuer - 但事实并非如此。

但是,如果我删除了use utf8。这与我认为use utf8的目的相反:表示脚本以UTF-8编码。

回答

9

问题在于字符边界。你是一个字节编码字符串比较解码字符串

$fuer = pack('H*', '66c3bc72')创建四个字节的字符串"\x66\xc3\xbc\x72",而小U与二分法ü"\xfc"所以如果你使用decode_utf8两个不匹配

Encode模块进一步处理您的变量$fuer那就解码UTF-8,形成三个字符"\x66\xfc\x72",然后替代将工作

use utf8适用相当于decode_utf8整个源文件,所以没有你ü它出现编码"\xc3\xbc",其包装可变

+1

感谢您的回答 - 这是第一次,我相信(希望...),我才明白'使用utf8'的东西。另外,我并不知道Perl具有字符边界的概念。我总是认为一个字符串只是(而且只是)一个字节数组。因此我的困惑。 –

4

比赛让我们搬出üs///,进入其自己的变量,所以我们可以检查它。

use utf8;        # Script is encoded using UTF-8 
use open ':std', ':encoding(UTF-8)'; # Terminal expects UTF-8. 

use strict; 
use warnings; 

my $uuml = "ü"; 
printf("%d %vX %s", length($uuml), $uuml, $uuml); # 1 FC ü 

my $fuer = pack('H*', '66c3bc72'); 
printf("%d %vX %s", length($fuer), $fuer, $fuer); # 4 66.C3.BC.72 für 

$fuer =~ s/\Q$uuml/!!!/; 
printf("%d %vX %s", length($fuer), $fuer, $fuer); # 4 66.C3.BC.72 für 

,因为这会使明显,你是对的üC3 BC)的UTF-8编码比较üFC)Unicode代码点。

所以,是的,use utf8;表示脚本是使用UTF-8编码的......但它这样做是为了让Perl可以正确解码脚本。

解码所有输入并编码所有输出!解决的办法是更换

my $fuer = pack('H*', '66c3bc72'); 

use Encode qw(decode_utf8); 

my $fuer = decode_utf8(pack('H*', '66c3bc72')); 

my $fuer = pack('H*', '66c3bc72'); 
utf8::decode($fuer);