为什么使用“use utf8”在UTF-8编码的Perl脚本中无法识别变音符号?

时间:2017-02-11 11:02:14

标签: perl utf-8 character-encoding

以下脚本以UTF-8编码:

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编码的。

2 个答案:

答案 0 :(得分: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"会将编码显示为bash,打包变量

答案 1 :(得分: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

这很明显,您将üFC)的Unicode代码点与üC3 BC)的UTF-8编码进行比较。

所以是的,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);