【问题标题】:How can I convert non-ASCII characters encoded in UTF8 to ASCII-equivalent in Perl?如何将 UTF8 编码的非 ASCII 字符转换为 Perl 中的 ASCII 等效字符?
【发布时间】:2026-02-10 23:30:02
【问题描述】:

我有一个 Perl 脚本,第三方正在调用它来向我发送注册我的软件的人员的姓名。其中一方使用 UTF-8 对名称进行编码,因此我相应地调整了我的脚本,以使用 Encode::decode_utf8(...) 将 UTF-8 解码为 ASCII。

这通常可以正常工作,但每 6 个月左右,其中一个名称包含西里尔字母、希腊语或罗马尼亚语字符,因此对名称进行解码会产生垃圾字符,例如“ПодражанÑÐºÐ°Ñ ”。我必须跟进客户并要求他提供其姓名的“拉丁字符版本”,以便颁发注册码。

那么,是否有任何 Perl 模块可以检测是否存在此类字符并在必要时自动将它们转换为最接近的 ASCII 表示?

似乎我可以使用 Lingua::Cyrillic::Translit::ICAO 加上 Lingua::DetectCharset 来处理 Cyrillic,但我更喜欢与其他字符集一起使用的东西。

【问题讨论】:

    标签: perl utf-8 character-encoding ascii


    【解决方案1】:

    我相信您可以为此使用Text::Unidecode,这正是它试图做的。

    【讨论】:

    • 正是我想要的 - 谢谢! :-)
    【解决方案2】:

    在 Text::Unicode 的文档中,在“注意事项”下,该短语似乎不正确:

    确保输入数据确实是 utf8 字符串。

    UTF-8 是一种可变长度编码,而 Text::Unidecode 只接受每个字符的固定长度(两字节)编码。所以这句话应该是:

    确保输入数据确实是一串两字节的 Unicode 字符。

    这也称为 UCS-2。

    如果你想转换真正是 utf8 的字符串,你可以这样做:

    my $decode_status = utf8::decode($input_to_be_converted);
    my $converted_string = unidecode ($input_to_be_converted);
    

    【讨论】:

      【解决方案3】:

      如果您必须处理不在 ascii 范围内的 UTF-8 数据,最好的办法是更改您的后端,这样它就不会被 utf-8 阻塞。您将如何音译汉字符号?

      【讨论】:

      • 在 10 多年的共享软件开发中,我只有少数来自日本和中国的客户。我所有的共享软件程序都启用了 Unicode,只是为了解决轻微的烦恼,这会被夸大了。在这种情况下,我更多的是寻找一种快速而肮脏的方法。
      • 所以也许(只是也许),如果启用 utf-8,您可能会发现更多客户?
      • 一些:是的。很多,值得花时间开发:不。盗版在共享软件业务中是一个非常大的问题,尤其是在像中国这样的国家。日本市场还不错,但据我从其他共享软件作者那里听说,除非你有一个非常大的标题,否则通常不值得。
      【解决方案4】:

      如果您得到西里尔文本,则许多字符没有“最接近的 ASCII 表示”。

      【讨论】:

      • +1。音译不是简单的替换单个字符的业务。要么正确支持 Unicode,要么只支持 ASCII;介于两者之间的任何事情都会很快变得混乱。
      • 尽管如此,每当我向来自俄罗斯的人询问他的名字时,他都能提供它的拉丁字符版本。我知道有些字符只是粗略的近似,但显然我的问题必须有一个解决方案。
      • 好吧,他们给你的一些拉丁等价名字并不是他们的“真实”名字。
      • 他们给你的是一种发音方式 - 转录,而你正在寻找音译,这是一个不同的问题。
      • 我同意。如果这些字符有 ASCII/拉丁文等价物,他们就不必一开始就发明 Unicode。