(看似)相同的字符串不同地转换为大写字母

Zip*_*970 2 string perl uppercase

转换为两个"相同"字符串的大写时,我遇到了一个非常奇怪的问题.该程序正在从网站读取行并将其与存储在文本文件中的行进行比较.如果找不到该行,则将其添加到文件末尾.除非该行包含特殊字符,否则此操作完美.由于某种原因,比较导致不匹配.我通过首先将它们转换为大写来比较两个字符串,这就是它出错的地方.下面是一些代码.我省略了填充两个变量的部分.我只是展示了奇怪的部分.

print "$pageLine <-> $dbLine\n";
print uc( $pageLine ) . " <-> " . uc( $dbLine ) . "\n";
Run Code Online (Sandbox Code Playgroud)

这导致了

Diëtisten <-> Diëtisten
DIëTISTEN <-> DIËTISTEN
Run Code Online (Sandbox Code Playgroud)

请注意,第一个中的ë不会转换为大写.

foreach my $kar (split( //, $pageLine) ) {
  print ord($kar) . ":";
}
print "\n";
foreach my $kar (split( //, $dbLine) ) {
  print ord($kar) . ":";
}
print "\n";
Run Code Online (Sandbox Code Playgroud)

这导致:

68:105:235:116:105:115:116:101:110:32:40:78:86:68:41:
68:105:235:116:105:115:116:101:110:32:40:78:86:68:41:
Run Code Online (Sandbox Code Playgroud)

有人知道这里发生了什么吗?

提前致谢.

ike*_*ami 6

最小的演示:

my $s = "\xEB";
utf8::downgrade( my $d = $s );
utf8::upgrade(   my $u = $s );
printf "%vX %vX %s\n", $d, $u, $d eq $u ? "same" : "different";
$_ = uc($_) for $d, $u;
printf "%vX %vX %s\n", $d, $u, $d eq $u ? "same" : "different";
Run Code Online (Sandbox Code Playgroud)

输出:

EB EB same
EB CB different
Run Code Online (Sandbox Code Playgroud)

默认情况下,为了向后兼容,uc如果输入标量的UTF8标志关闭,则只会使用大写的ASCII字符.这是通过添加以下内容修复的Unicode Bug [1]的一个实例:

use feature qw( unicode_strings );
Run Code Online (Sandbox Code Playgroud)

以上内容可以通过添加以下内容间接完成:

use 5.012;
Run Code Online (Sandbox Code Playgroud)

参考文献:unicode_strings,feature,use


  1. 当代码的行为取决于字符串的存储格式时,该代码就会受到Unicode Bug的影响.