Perl下拉菜单和Unicode

时间:2017-10-27 22:04:51

标签: perl unicode encoding utf-8

我一直在讨论这个问题已经有一段时间了,并且不能完全理解。这是Ubuntu上的Perl 5。我的网页上有一个下拉列表:

$output .= start_form . "Student: " . popup_menu(-name=>'student', -values=>['', @students], -labels=>\%labels, -onChange=>'Javascript:submit()') . end_form;

它只是来自SQL Server表格的“Last,First”形式的一组名称。标签是从SQL列创建的,如下所示:

$labels{uc($record->{'id'})} = $record->{'lastname'} . ", " . $record->{'firstname'}; 

问题是下拉列表没有正确显示某些Unicode字符。例如,“Søren”在下拉列表中显示为“Søren”。我有我的标题:

use utf8;
binmode(STDOUT, ":utf8");

...而且我也玩过“ decode()”功能,但无济于事。对我来说,有趣的是,如果我将 $ labels 拉入测试脚本并将列表打印到控制台,名称就会显得很好!那么导致这种下拉的原因是什么呢?提前谢谢。

编辑:

这是相关的功能,我已经剥离了这个在控制台中运行的脚本,为三个具有Unicode字符的条目生成了正确的结果

#!/usr/bin/perl

use DBI;
use lib '/home/web/library';
use mssql_util;
use Encode;

binmode(STDOUT, ":utf8");

$query = "[SQL query here]";

$dbh  = &connect;
$sth  = $dbh->prepare($query);
$result = $sth->execute();

while ($record = $sth->fetchrow_hashref())
{
        if ($record->{'id'})
        {
                $labels{uc($record->{'id'})} = Encode::decode('UTF-8', $record->{'lastname'} . ", " . $record->{'nickname'} . " (" . $record->{'entryid'} . ")");
        }
}

$sth->finish();

print "$labels{'ST123'}\n";
print "$labels{'ST456'}\n";
print "$labels{'ST789'}\n";

生产脚本的不同之处在于,不是像上面那样打印到控制台,而是打印到HTTP:

$my_output = "<p>$labels{'ST123'}</p><br>
              <p>$labels{'ST456'}</p><br>
              <p>$labels{'ST789'}</p>";

$template =~ s/\$body/$my_output/;

print header(-cookie=>$cookie) . $template; 

这会在页面上显示“ZoÔ和“Søren”之类的字符串。但是,如果我从生产脚本的顶部删除binmode(STDOUT, ":utf8");,那么字符串在页面上显示就好了(即我得到“Zoë”和“Søren”)。

我认为在将UTF-8写入输出时必须使用binmode()行,而在此处删除它会产生正确的结果。是什么给了什么?

2 个答案:

答案 0 :(得分:3)

问题#1:解码输入

53.C3.B8.72.65.6ESøren的UTF-8编码。当你指示Perl重新编码它时(通过打印它来处理:utf8图层),你就会产生垃圾。

您需要解码输入($record->{id}$record->{lastname}$record->{firstname}等)!这会将UTF-8字节53.C3.B8.72.65.6E(“编码文本”)转换为Unicode代码点53.F8.72.65.6E(“已解码文本”)。

在此表单中,您将能够使用uc,正则表达式匹配等。您还可以将它们打印到带有编码层的句柄(例如:encoding(UTF-8)),或者不正当:utf8)。

您可以告诉我们这些输入来自数据库。大多数DBD都有一个标志,可以解码字符串。例如,如果它是MySQL数据库,则应将mysql_enable_utf8mb4 => 1传递给connect

问题#2:传达编码

如果您要输出UTF-8,请不要告诉浏览器它是ISO-8859-1!

$ perl -e'use CGI qw( :standard ); print header()'
Content-Type: text/html; charset=ISO-8859-1

修正:

$ perl -e'use CGI qw( :standard ); print header( -type => "text/html; charset=UTF-8" )'
Content-Type: text/html; charset=UTF-8

答案 1 :(得分:2)

很难给出明确的解决方案,因为您没有给我们提供更多有用的信息。但这里有一些可能会有所帮助的指示。

  • p只告诉Perl您的源代码编码为UTF-8。它没有任何用处。
  • 阅读perldoc perlunitut将是一个良好的开端。
  • 您知道数据库表的编码方式吗?
  • 您是否知道您的数据库连接是否配置为自动将来自数据库的数据解码为Perl字符?
  • 您告诉浏览器您编写了HTTP响应的编码是什么编码?