我已经研究这个问题有一段时间了,但不太明白。这是 Ubuntu 上的 Perl 5。我的网页上有一个下拉列表:
$output .= start_form . "Student: " . popup_menu(-name=>'student', -values=>['', @students], -labels=>\%labels, -onChange=>'Javascript:submit()') . end_form;
它只是来自 SQL Server 表的一组“姓、名”形式的名称。标签是从 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( ) 行是必需的,但在这里删除它会产生正确的结果。给出了什么?
最佳答案
问题#1:解码输入
53.C3.B8.72.65.6E
是 Sø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
关于Perl 下拉菜单和 Unicode,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46984007/