Perl 字符串操作和 utf8/unicode
Perl string manipulation and utf8/unicode
在人们开始将包含 utf8 字符的 Wikipedia 文本字符串复制并粘贴到输入字段之前,我一直认为这是一个简单的 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
的值有一个 'u',上面有一个变音符号,就在“-W”之后。
当我 运行 脚本时,我得到:
# ./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-umlaut 去哪儿了?我如何取回它?
%C3%BC
是 ü
的 urlencode
。对于 MySQL,您不需要它,但在构建 URL.
时可能需要它
ü
当您将 utf8 字节作为 latin1 存储到 latin1 列时会发生。请提供 SHOW CREATE TABLE
.
我认为你不需要 encode/decode_utf8 任何东西。
Malformed UTF-8 character (unexpected non-continuation byte 0x72, immediately after start byte 0xfc) at ./test.pl line 13.
表示你有十六进制 FC
(这是 latin1 十六进制 ü
),但你将字符串视为 utf8("unexpected ..") 72
是后面的 r
.
底线:您在整个处理过程中都不是 utf8(手头的字节、SET NAMES、CHARACTER SET 等)。
问题 1
您告诉 Perl 您的源文件是使用 UTF-8 编码的。
use utf8;
事实并非如此。 ü
在您的文件中由 FC
而不是 C3 BC
表示。 (这就是您收到 "malformed" 消息的原因。)修复源文件的编码。
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
原来 Rick James 的最后一行 Bottom line: You are not utf8 throughout the processing (bytes in hand, SET NAMES, CHARACTER SET, etc).
是关键。我确实需要 Encode 模块,但仅适用于 DB 插入语句,a la:
if (!($sth->execute(encode('UTF-8', $_))) && $DBI::err != 1062) {
die "DB execute failed :" . $DBI::err . ": " . $DBI::errstr;
}
谢谢大家
在人们开始将包含 utf8 字符的 Wikipedia 文本字符串复制并粘贴到输入字段之前,我一直认为这是一个简单的 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
的值有一个 'u',上面有一个变音符号,就在“-W”之后。
当我 运行 脚本时,我得到:
# ./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-umlaut 去哪儿了?我如何取回它?
%C3%BC
是 ü
的 urlencode
。对于 MySQL,您不需要它,但在构建 URL.
ü
当您将 utf8 字节作为 latin1 存储到 latin1 列时会发生。请提供 SHOW CREATE TABLE
.
我认为你不需要 encode/decode_utf8 任何东西。
Malformed UTF-8 character (unexpected non-continuation byte 0x72, immediately after start byte 0xfc) at ./test.pl line 13.
表示你有十六进制 FC
(这是 latin1 十六进制 ü
),但你将字符串视为 utf8("unexpected ..") 72
是后面的 r
.
底线:您在整个处理过程中都不是 utf8(手头的字节、SET NAMES、CHARACTER SET 等)。
问题 1
您告诉 Perl 您的源文件是使用 UTF-8 编码的。
use utf8;
事实并非如此。 ü
在您的文件中由 FC
而不是 C3 BC
表示。 (这就是您收到 "malformed" 消息的原因。)修复源文件的编码。
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
原来 Rick James 的最后一行 Bottom line: You are not utf8 throughout the processing (bytes in hand, SET NAMES, CHARACTER SET, etc).
是关键。我确实需要 Encode 模块,但仅适用于 DB 插入语句,a la:
if (!($sth->execute(encode('UTF-8', $_))) && $DBI::err != 1062) {
die "DB execute failed :" . $DBI::err . ": " . $DBI::errstr;
}
谢谢大家