Split函数返回奇怪的字符

时间:2014-06-20 13:40:51

标签: perl

我正面临着我想制作的剧本的问题。简而言之,我使用dbi连接到本地数据库并执行一些查询。虽然这很好用,并且当我从select查询中打印出返回的值等等时,当我将$ firstName拆分为数组并打印出数组时,我会得到奇怪的字符。请注意,我正在使用的表中的所有字段仅包含希腊字符,并且是utf8_general_ci。我玩过使用utf8,使用编码,binmode,编码等但仍然拆分功能确实返回we奇怪的字符,而在拆分之前整个希腊字打印得很好。我想这是由于关于字符串编码的一些缺失的pragma或类似的东西,但实际上无法找到解决方案。提前致谢。 这是我描述的一段代码。 Perl版本是v5.14.2

@query = &DatabaseSubs::getStringFromDb(); 
print "$query[1]\n";  # prints the greek name fine 
@chars = split('',$query[1]); 
foreach $chr (@chars) { 
    print "$chr \n";  # prints weird chars 
}

here分别是print和foreach的输出。

3 个答案:

答案 0 :(得分:2)

你的数据是在utf8中,但是perl并不知道,因此每个perl字符只是存储在数据库中的多字节字符的一个字节。

你告诉perl数据实际上是utf8:

utf8::decode($query[1]);

(尽管大多数数据库驱动程序提供了一种在您查看代码中的数据之前自动执行此操作的方法)。完成此操作后,拆分将对实际字符进行正确操作。您可能还需要将输出文件句柄设置为期望utf8字符,否则它会尝试将它们降级为8位编码。

答案 1 :(得分:2)

默认情况下,Perl假定您使用的是单字节字符。但是你不是,在UTF8中,你使用的希腊字符的大小是两个字节。因此,split会将您的角色分成两半并且您会变得很奇怪。

您需要在进入程序时将字节解码为字符。一种方法就是这样。

use Encode;

my @query = map { decode_utf8($_) } DatabaseSubs::getStringFromDb();

(我还从子程序调用中删除了不必要的,可能令人困惑的'&')

现在@query包含正确解码的字符串,split会正确分割成单个字符(*)。

但如果你打印其中一个角色,你就会得到一个宽广的角色"警告。这是因为Perl的I / O层需要单字节字符。你需要告诉它期待UTF8。你可以这样做:

binmode STDOUT, ':utf8';

您可以考虑其他改进。例如,您可以将解码放入getStringFromDb子例程。我建议您阅读perldoc perluniintroperldoc perlunicode了解详情。

(*)是的,当你进入两个字符的字形时,潜伏着另一个整体的痛苦,但是现在让我们忽略它。

答案 2 :(得分:0)

问题是split('', $word)分裂每个字节 utf8中你可以有多字节字符。对于ASCII值小于127的字符,这很好,但超过127的任何字符都表示为多个字节。你基本上打印了一半字符的代码,因此它看起来像垃圾。