使用Perl的Unicode杂耍

时间:2011-11-23 13:01:21

标签: perl utf-8 utf8-decode

我有一个问题,我认为是微不足道的。我必须处理德语字母表中的变形金刚(äöü)。在Unicode中,似乎有几种方法可以显示它们,其中一种方法是组合字符。我需要规范化这些不同的方式,用一个字符的代码替换它们。

很容易找到这样一个离经叛道的变音符号:它是一个字母aou,后跟UTF-8字符\uCC88。所以我认为正则表达式就足够了。

这是我的转换功能,使用Encoding包。

# This sub can be extended to include more conversions
sub convert {
    local $_;
    $_ = shift;

    $_ = encode( "utf-8", $_ );

    s/u\xcc\x88/ü/g;
    s/a\xcc\x88/ä/g;
    s/o\xcc\x88/ö/g;
    s/U\xcc\x88/Ü/g;
    s/A\xcc\x88/Ä/g;
    s/O\xcc\x88/Ö/g;

    return $_;
}

但是由此产生的印刷变音符号是一些更狡猾的字符(现在占用4个字节),而不是list上的那个。

我想这个问题就是用Perl的内部格式,实际的UTF-8和这种编码格式来解决这个问题。

甚至将替换行更改为

s/u\xcc\x88/\xc3\xbc/g;
s/a\xcc\x88/\xc3\xa4/g;
s/o\xcc\x88/\xc3\xb6/g;
s/U\xcc\x88/\xc3\x9c/g;
s/A\xcc\x88/\xc3\x84/g;
s/O\xcc\x88/\xc3\x96/g;

没有帮助,它们被正确转换,然后在字节中跟着“\ xC2 \ xA4”。

任何帮助?

1 个答案:

答案 0 :(得分:10)

你做错了:你必须停止在表示层面上弄乱字符的习惯,即在处理文本而不是二进制数据时不要使用正则表达式中的字节。

第一步是了解encoding in Perl的主题。你需要这个来理解我将在下面的段落中使用的术语“字符串”。

当你有字符串时,它可能处于(de)组合的各种状态。使用模块Unicode::Normalize更改字符串,并在Unicode规范中阅读有关等效性和规范化的相关章节以获取详细信息,它们链接在该模块文档的底部。

我想你想要NFC,但你必须对你的数据进行健全性检查,看看这是否真的是预期的结果。

use charnames qw(:full);
use Unicode::Normalize qw(NFC);
my $original_character_string = "In des Waldes tiefsten Gr\N{LATIN SMALL LETTER U WITH DIAERESIS}nden ist kein R\N{LATIN SMALL LETTER A}\N{COMBINING DIAERESIS}uber mehr zu finden.";
my $modified_character_string = NFC($original_character_string);
# "In des Waldes tiefsten Gr\x{fc}nden ist kein R\x{e4}uber mehr zu finden."