perl - 为什么使用非拉丁字母语言环境的 Encode::decode 在本地化 strftime 输出上会崩溃?

标签 perl utf-8 locale

在带有 Perl 5.26.1 的 Ubuntu 上,我在使用 Dancer::Logger::Console 时遇到了以下问题。我已将此代码从 Dancer2::Core::Role::Logger 中取出.

为了运行它,您需要生成以下区域设置:

sudo locale-gen de_DE.UTF-8
sudo locale-gen ko_KR.UTF-8

此示例代码使用韩语区域设置,失败时不会显示错误消息。 $@ 为空。

$ LC_ALL=ko_KR.UTF-8 perl -MPOSIX -MEncode -E 'eval {
    say Encode::decode("UTF-8", strftime("%b", localtime))
  }; 
  say $@;
  '
Wide character at -e line 1.

当使用德语语言环境运行时,它会成功(但会抛出宽字符警告,我们可以在此测试中忽略该警告)。

$ LC_ALL=de_DE.UTF-8 perl -MPOSIX -MEncode -E 'eval {
    say Encode::decode("UTF-8", strftime("%b", localtime))
  }; 
  say $@;
  '
Wide character in say at -e line 2.
M�r

%b 格式是将月份缩写为本地化单词(请参阅 http://strftime.net/ )。

如果我们不Encode::decode("UTF-8", ...),它就会起作用,上面的韩语版本会生成 3월 .

这是怎么回事?

最佳答案

ko_KR.UTF-8 下,strftime("%b", localtime(1552997524)) 返回 20.33.C6D4。当解释为 Unicode 代码点时,这是“␠3월”(“三月”,带前导空格)。

de_DE.UTF-8 下,strftime("%b", localtime(1552997524)) 返回 4D.E4.72。当解释为 Unicode 代码点时,这是“Mär”(“März”、“March”的缩写形式)。

所以看起来解码文本(Unicode 代码点)正在返回,这是完美的。剩下要做的就是对输出进行编码

$ LC_ALL=ko_KR.UTF-8 perl -CSD -MPOSIX -e'CORE::say strftime("%b", localtime)'
 3월

$ LC_ALL=de_DE.UTF-8 perl -CSD -MPOSIX -e'CORE::say strftime("%b", localtime)'
Mär

在程序中(而不是单行程序),您可以使用类似以下内容来代替 -CSD:

use open ':std', ':encoding(UTF-8)';

关于perl - 为什么使用非拉丁字母语言环境的 Encode::decode 在本地化 strftime 输出上会崩溃?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55240390/

相关文章:

java - 字符串类内部 - 如果使用 UTF-8,缓存字符偏移到字节关系

python-2.7 - Pandas 将对象列转换为 str - 列包含 unicode、float 等

java - 如何使用 Strings.xml 更改文本值 - AndroidX

PHP 货币格式

c++ - c++读取txt文件(中文)

RegEx 和 Mod_rewrite 将动态 URL 转换为静态 URL,将静态 URL 转换为动态 URL

python - 使用 win32com 模块的 Python 2.7 中的 Qualcomm QPST 自动化服务器

Perl 将字符串转换为 8 个十六进制数字组

php - 如果文件名是 UTF-8,使 PHP pathinfo() 返回正确的文件名

encoding - JMeter CSV 数据集破坏了以正确的 UTF-8 格式存储的日文字符串,我得到的是问号