【问题标题】:Perl string manipulation and utf8/unicodePerl 字符串操作和 utf8/unicode
【发布时间】:2015-07-11 12:27:06
【问题描述】:

在人们开始从 Wikipedia 复制并粘贴包含 utf8 字符的文本字符串到输入字段之前,我认为这将是一个简单的 Web 表单。我的 perl CGI 脚本打开一个 MySQL 数据库连接并设置

$DBH->{mysql_enable_utf8} = 1;
$DBH->do("set names 'utf8';");

我正在尝试使用Encode 模块对目标输入值进行解码、使用和编码,但这并不符合我的预期。网页设置为 utf8 字符集。

在这种情况下,我的目标字符串是Baden-Württemberg [复制自列出德国城镇名称的维基百科页面]。发送请求后,我可以看到目标字符串为:Baden-W%C3%BCrttemberg。但这并不能很好地通过我的 CGI 脚本。

我有以下示例脚本:

#!/usr/local/bin/perl -w

use strict;
select(STDOUT);
$|++;

use feature 'unicode_strings';
use Encode;
use utf8;

binmode STDOUT, ":utf8";

my $thing = "Baden-Württemberg";
print STDOUT "$thing\n";

my $decodedThing = decode_utf8($thing);
print STDOUT encode_utf8($decodedThing) . "\n";

$thing 的值在“-W”之后有一个带有变音符号的“u”。

当我运行脚本时,我得到:

# ./test.pl
Malformed UTF-8 character (unexpected non-continuation byte 0x72, immediately after start byte 0xfc) at ./test.pl line 13.
Baden-Wrttemberg
Baden-Wrttemberg

u 变音符号去哪儿了?如何找回?

【问题讨论】:

    标签: mysql perl utf-8


    【解决方案1】:

    原来 Rick James 的最后一行 Bottom line: You are not utf8 throughout the processing (bytes in hand, SET NAMES, CHARACTER SET, etc). 是关键。我确实需要 Encode 模块,但仅适用于 DB 插入语句,例如:

    if (!($sth->execute(encode('UTF-8', $_))) && $DBI::err != 1062) {
        die "DB execute failed :" . $DBI::err . ": " . $DBI::errstr;
    }
    

    谢谢大家

    【讨论】:

      【解决方案2】:

      问题 1

      您告诉 Perl 您的源文件是使用 UTF-8 编码的。

      use utf8;
      

      事实并非如此。 ü 在您的文件中由 FC 表示,而不是 C3 BC。 (这就是您收到“格式错误”消息的原因。)修复源文件的编码。

      mv file.pl file.pl~ && piconv -f iso-8859-1 -t UTF-8 file.pl~ >file.pl
      

      问题 2

      以下内容毫无意义:

      my $decodedThing = decode_utf8($thing);
      

      因为use utf8;$thing 已经被解码了。

      问题 3

      以下内容毫无意义:

      print STDOUT encode_utf8($decodedThing);
      

      你要求 Perl 自动编码每一个发送到 STDOUT 的文件,所以你是双重编码。

      已修复

      #!/usr/local/bin/perl
      
      use strict;
      use warnings;
      use utf8;
      use open ':std', ':encoding(UTF-8)';
      
      my $thing = "Baden-Württemberg";
      printf "U+%v04X\n", $thing;     # U+[...].0057.00FC.0072.[...]
      print "$thing\n";               # Baden-Württemberg
      

      【讨论】:

        【解决方案3】:

        %C3%BCurlencodeü。您不希望 MySQL 使用它,但在构建 URL 时可能需要它。

        ü 发生在您将 utf8 字节存储为 latin1 到 latin1 列时。请提供SHOW CREATE TABLE

        我认为你不需要 encode/decode_utf8 来做任何事情。

        ./test.pl 第 13 行的格式错误的 UTF-8 字符(意外的非连续字节 0x72,紧跟在开始字节 0xfc 之后)。

        表示您有十六进制 FC(这是 ülatin1 十六进制),但您将字符串视为 utf8(“unexpected ..”)72r 紧随其后。

        底线:您在整个处理过程中都不是 utf8(手头的字节、SET NAMES、CHARACTER SET 等)。

        【讨论】:

        • 创建表nameTokens (id int(11) unsigned NOT NULL AUTO_INCREMENT, token varchar(128) NOT NULL, 主键 (id), 唯一键 token ( token) ) ENGINE=InnoDB AUTO_INCREMENT=124 默认字符集=utf8
        猜你喜欢
        • 2021-06-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-25
        • 2013-08-20
        • 1970-01-01
        • 2010-12-07
        • 1970-01-01
        相关资源
        最近更新 更多