2

我有一个我认为微不足道的问题。我必须处理来自德语字母 ( äöü) 的变音符号。在 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 个字节),而不是这个列表中的那个。

我想问题在于 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”。

有什么帮助吗?

4

1 回答 1

10

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

第一步是了解Perl 中的编码主题。您需要它来理解我将在下一段中使用的术语“字符串”。

当您有字符串时,它可能处于(分解)组合的任何各种状态。使用模块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."
于 2011-11-23T13:38:04.523 回答