使用Perl的Unicode杂耍

Lan*_*nbo 2 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 $_;
}
Run Code Online (Sandbox Code Playgroud)

但是由此产生的印刷变音符号是一些更狡猾的字符(现在占用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;
Run Code Online (Sandbox Code Playgroud)

没有帮助,他们正确转换,但后面跟着字母"\ xC2\xA4".

有帮助吗?

dax*_*xim 10

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

第一步是了解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."
Run Code Online (Sandbox Code Playgroud)

  • NFC已涉及分解步骤,请参阅UAX#15. (2认同)