尽管到 Perl 6 中才宣称完全支持 Unicode,但是在 Perl 5.8.6 中内嵌的对 Unicode 的支持已经足以开始编写本地化的应用程序了。Ted 使用自己所钟爱的编辑器 Yudit,介绍了 Perl 怎么样读取、解释和处理 UTF-8 编码的 Unicode。
从 5.6.0 版本发布以来,Perl 已经发生了极大的变化。Perl 6 项目是在一个名为 Parrot 的解释器(它内嵌了对 UTF-8 和很多其他与 Unicode 有关的特性的支持)的基础上构建和运行的(我知道这种说法太过简单,但是本文后面马上要介绍的内容可以确保您并不需要担心这些细节)。因此,Perl 6 从一开始就非常重视对 Unicode 的支持。(所以,在 Perl 6 发布时我还会撰写另外一篇有关 Perl 6 的 Unicode 文章。我当然希望这很快就可以实现。到时候我就不会只是这么简单地提一下就算完了!)
在撰写本文时,我参考的是 5.8.6 版本,但是目前最新版本是 5.8.7。我并没有对 CPAN 的任何 Unicode 模块进行测试 —— 尽管这些模块的确存在,而且也可以很好地工作 —— 因为我们在本文中重点讨论的是 Perl 中内嵌的对 Unicode 的支持特性。因此,我所测试的目标是 Perl 的 Unicode(UTF-8 编码)的读取、解释和处理能力。在本文中我也并没有讨论 Unicode、UCS 和 UTF-8 编码的内容 —— 在 参考资料 中可以找到介绍这个主题的丰富资源。
我喜欢使用 Yudit 编辑器和 rxvt(Unicode 版本)的终端来进行有关 Unicode 的工作。(我一直在使用 rxvt,而不是 xterm;它们都可以很好地处理一些简单的事情,但是从我的观点来看,rxvt 要更好些,因为它可以使用多种字体来显示不同的字符集。)
Unicode 的准备
为了这篇使用 UTF-8 编码的文章,我做好了所有的工作。您应该可以在大部分现代 UNIX® 系统中安装 rxvt-unicode 终端包。您还需要确保支持一个 UTF-8 locale,这与 OS 有关。通常来说,您应该可以这样做:setenv LANG en_US.UTF-8; rxvt-unicode,然后就可以了;但是有些系统,例如 Debian Linux,可能需要其他一些步骤来启用 UTF-8 locale(通常它们默认是没有启用的)。另外, en_US.UTF-8 可能对于您来说并不是一个合适的 locale。您可以检查自己的 OS 手册 和 HOWTO 文档。
您应该安装 Yudit 编辑器,它的功能非常强大,而且非常容易使用。您也可以使用 CVS 版本的 Emacs,我所使用的是 2005 年 1 月的版本(当前的稳定版本是 21.4)。Emacs 可以读写 UTF-8 编码的文件,在我的实验中都非常稳定 —— 只是对于高级的 Unicode 工作来说,功能没有 Yudit 强大。
注意:在为本文提供的脚本中,已经 包括了 use strict; 和 use warnings; 附注(pragmas)(您可以从下面的 下载 部分下载 cp35.zip 文件,其中包含有这些附注)。一直启用这些附注就不会出现一些导致遗憾的错误。
打印 Unicode 字符
关于 Unicode,最基本的事情(也是最有用的事情)可能就是它让程序可以打印超出 ASCII 和 Latin-1 字符集范围的字符。因此,怎么样打印 Unicode 字符呢?chr() 函数可以实现这种功能。例如,0x30A4 是日文中的一个片假名,它看起来就像是“T”,不过上面的横线是斜向上的:
图 1. 日文片假名字符“I”(“ee”)
要打印这个片假名,后面再跟上一个笑脸符号,可以输入:
perl -e'binmode(STDOUT, ":utf8"); print chr(0x30A4), chr(0x263a)'
注意 binmode() 调用。如果没有这个调用,或者等效的 -C 开关,Perl 就会打印一个打印语句中有宽数据的警告信息(详细信息请参阅 perldoc perlunicode 和 perldoc perlrun)。从我的观点来看,这只是 1% 的 Perl 用户需要使用的一个特性;其他 99% 的用户都需要忍受这个警告,或者额外编写一些代码来处理它。默认启用这个警告信息并不是什么好主意。
显然,如果您有很多东西需要输入,通过编码(或名字,Perl 也可以使用名字实现相同的功能)来指定字符实在是件痛苦的事情。怎么样才能以 UTF-8 的形式给 Perl 提供数据呢?script 2.pl 在脚本中就直接嵌入了 UTF-8 编码的数据。
这个脚本的工作与 HERE 文档类似。Script 3.pl 会分别以英语、保加利亚语和俄语来打印“您好”。
不幸的是,UTF-8 数据并不被支持作为 HERE 标记(marker)。因此,script 4.pl 会报告一个错误“Can't find string terminator \343 anywhere before EOF at ./4.pl line 7.”(其中 \343 是一个无关字符)。
这可太糟了;单个 Unicode 字符可以作为 HERE 标记。它是简短的、富有表现力的且不太可能出现在文本中的字符(如果仔细选择的话。例如笑脸符号)。不幸的是,use utf8; 并不能使用 Unicode HERE 标记。
您可以给一个变量分配一个 HERE 文档,而不是简单地打印这个变量,这样就需要在脚本中使用 use utf8;(请参阅 清单 8)。
识别 Unicode 字符
与打印 Unicode 数据相对的就是怎么样识别这些数据。内嵌的 ord() 函数怎么样执行?我在 脚本 5.pl 中对此逐一进行了检查,它可以很好地工作。从编码到字符的映射是一对一的,从字符到编码的映射也是一对一的。这是一个非常简单但却非常重要的测试;怎么样才能确保一个字符只会映射为一个惟一的编码呢?
Tags:特性 使用 学习 Unicode 可以 Perl 一个 字符 UTF-8 编码
|