Perl脚本中Unicode转译字符与数据库字符比较失败的修复方案
问题根源
- en_US.819对应的是ISO-8859-1编码,这个编码原本就没包含欧元符号(€)——€是后来加到ISO-8859-15里的,所以从这个区域设置的数据库里根本读不出€,
$expected自然是空的。 - 你的Perl脚本是ANSI编码,
chr($1)默认生成的是本地编码的字符,不是Unicode,就算能生成€,也和数据库读出来的内容(或者空值)编码不匹配,肯定比不过。
解决方案
方案1:换数据库区域到支持€的编码
把数据库的区域设置改成en_US.ISO8859-15或者en_US.UTF-8,确保能正常读出€,同时调整脚本的编码处理逻辑:
# 脚本开头加编码声明,强制用UTF-8处理 use utf8; use open ':std', ':encoding(UTF-8)'; # 修改转换函数,确保生成Unicode字符 sub UnicodeDecHashNumsToText { my $str = shift; # 直接用十进制码点生成Unicode字符(Perl 5.14+支持) $str =~ s/#(\d+)/chr($1)/ge; return $str; } # 假设get_from_db是读取数据库的函数,读出来后转成Unicode use Encode qw(decode); my $expected = decode('ISO-8859-15', get_from_db()); # 如果用UTF-8就改成decode('UTF-8', ...) my $got = UnicodeDecHashNumsToText('#8364'); # 现在都是Unicode字符串,直接比较 if ($got eq $expected) { print "比较通过\n"; } else { print "比较失败\n"; }
方案2:直接在脚本里写死预期的€,不用读数据库
如果没法改数据库配置,干脆跳过数据库读取,直接在脚本里定义€的Unicode字符:
use utf8; # 必须加,不然脚本里的€会被当成乱码 my $expected = "€"; my $got = UnicodeDecHashNumsToText('#8364'); # 确保$got是Unicode编码,避免编码不匹配 use Encode qw(decode); $got = decode('UTF-8', $got) if !utf8::is_utf8($got); if ($got eq $expected) { print "比较通过\n"; }
方案3:让转换函数生成ISO-8859-15编码的字节
如果必须用en_US.819,但数据库实际存的是ISO-8859-15编码的€(大概率是数据库配置错了),可以让函数生成对应编码的字节:
use Encode qw(encode); sub UnicodeDecHashNumsToText { my $str = shift; # 先生成Unicode字符,再转成ISO-8859-15的字节 $str =~ s/#(\d+)/chr($1)/ge; return encode('ISO-8859-15', $str); } # 直接用数据库读出来的字节比较 my $expected = get_from_db(); my $got = UnicodeDecHashNumsToText('#8364'); if ($got eq $expected) { print "比较通过\n"; }
内容的提问来源于stack exchange,提问作者Alex Net
相关产品推荐
相关产品推荐

