当regexp仅包含ascii字符时,UTF-8编码字符串的字符串替换正常工作,但当regexp包含非ascii时会产生乱码输出。
my $str = "¿más?";
$str =~ s/[?]//g;
print "$str\n";
==> ¿MÁS
$str =~ s/[¿]//g;
print "$str\n";
==> MS
更新:上面的答案清楚地表明我的原始问题框架不佳。答案集中在STDOUT,但在我的实际问题中,我不打印到STDOUT。 (我只是为了简化问题陈述而这样做)。在实际问题中,我从sqlite存储中检索数据并使用数据作为文件名来搜索文件系统。当我将清理例程应用于检索到的数据时,某些文件名会出现乱码。
查看此信息的一种方法可能是进一步简化示例:
my $str = "más";
$str =~ s/[?]//g;
print "$str\n";
==> MÁS
$str =~ s/[¿]//g;
print "$str\n";
==> MS
现在你可以看到@ ikegami的解释不适用。关于第二个问题的问题///会产生问题。公平地说,这两个答案都解决了所述的问题 - 但任何额外的见解将不胜感激!
更新2:根据要求,添加了sprintf的矢量标志输出。注意:还将目标替换字符从¿更改为¡ - 我现在认为上面的代码(如@ikegami建议的)必须被错误地复制。
my $str = "más";
printf "%v02X\n", $str;
==> 6D.C3.A1.73
$str =~ s/[!]//g;
printf "%v02X\n", $str;
==> 6D.C3.A1.73
print "$str\n";
==> MÁS
$str =~ s/[¡]//g;
printf "%v02X\n", $str;
==> 6D.C3.73
print "$str\n";
==> MS
答案 0 :(得分:3)
#!/usr/bin/env perl
use strict;
use warnings;
use utf8;
binmode STDOUT, ':encoding(UTF-8)';
my $str = "¿más?";
$str =~ s/[?]//g;
print "$str\n";
$str = "¿más?";
$str =~ s/[¿]//g;
print "$str\n";
输出:
¿más
más?
答案 1 :(得分:3)
您正在查看源代码,就好像它是UTF-8一样,但除非您告诉Perl它的UTF-8,否则它会将其视为US-ASCII。
你说你有以下内容:
my $str = "más";
printf "%v02X %s\n", $str, $str;
$str =~ s/[!]//g;
printf "%v02X %s\n", $str, $str;
$str =~ s/[¡]//g;
printf "%v02X %s\n", $str, $str;
但你真的给Perl提供了以下内容:
my $str = "m\xC3\xA1s";
printf "%v02X %s\n", $str, $str; # 6D.C3.A1.73 (the UTF-8 of más)
$str =~ s/[!]//g;
printf "%v02X %s\n", $str, $str; # 6D.C3.A1.73 (the UTF-8 of más)
$str =~ s/[\xC2\xA1]//g; # Replaces either of these bytes
printf "%v02X %s\n", $str, $str; # 6D.C3.73 (garbage)
您需要以下内容:
use utf8; # Source is encoded using UTF-8
use open ':std', ':encoding(UTF-8)'; # Terminal provides and expects UTF-8.
my $str = "más";
printf "U+%v04X %s\n", $str, $str; # U+006D.00E1.0073 (the Unicode of más)
$str =~ s/[¡]//g; # Aka s/[\x{0041}]//g
printf "U+%v04X %s\n", $str, $str; # U+006D.00E1.0073 (the Unicode of más)
你提到你没有从源代码中获取字符串,并且你没有输出STDOUT,但修复是相同的:解码输入和编码输出。