Публикацията е актуализирана. Моля, преминете към частта за решение, ако вече сте прочели публикувания въпрос. Благодаря!
Ето минимизирания код за показване на моя проблем:
Файлът с входни данни за тест е запазен от вградения Notepad на Windows като UTF-8 кодиране. Той има следните три реда:
abacus æbәkәs abalone æbәlәuni abandon әbændәn
Скрипт файлът на Perl също е запазен от вградения Notepad на Windows като UTF-8 кодиране. Той съдържа следния код:
#!perl -w
use Data::Dumper;
use strict;
use autodie;
open my $in,'<',"./hash_test.txt";
open my $out,'>',"./hash_result.txt";
my %hash = map {split/\t/,$_,2} <$in>;
print $out Dumper(\%hash),"\n";
print $out "$hash{abacus}";
print $out "$hash{abalone}";
print $out "$hash{abandon}";
В изхода хеш-таблицата изглежда е наред:
$VAR1 = { 'abalone' => 'æbәlәuni ', 'abandon' => 'әbændәn', 'abacus' => 'æbәkәs ' };
Но всъщност не е, защото получавам само две стойности вместо три:
æbәlәuni әbændәn
Perl дава следното предупредително съобщение:
Use of uninitialized value $hash{"abacus"} in string at C:\test2.pl line 11, <$i
n> line 3.
къде е проблема Може ли някой любезно да обясни? Благодаря.
Решението
Милиони благодарности на всички вас :) Сега най-накрая виновникът е открит и проблемът става поправим :) Както @Sinan проницателно посочи, сега съм 100% сигурен, че виновникът за причиняването на проблема, който описах по-горе, са двамата байтове от BOM, които Notepad добави към моя файл с данни, когато беше записан като UTF-8 и които по някакъв начин Perl не третира правилно. Въпреки че мнозина предполагаха, че трябва да използвам "‹:utf8" и ">:utf8" за четене и запис на файлове, работата е там, че тези utf-8 конфигурации не решават проблема. Вместо това те могат да причинят някои други проблеми.
За да разреша наистина проблема, всичко, от което всъщност се нуждая, е да добавя един ред код, за да принудя Perl да игнорира BOM:
#!perl -w
use Data::Dumper;
use strict;
use autodie;
open my $in,'<',"./hash_test.txt";
open my $out,'>',"./hash_result.txt";
seek $in,3,0; # force Perl to ignore the BOM!
my %hash = map {split/\t/,$_,2} <$in>;
print $out Dumper(\%hash);
print $out $hash{abacus};
print $out $hash{abalone};
print $out $hash{abandon};
Сега резултатът е точно това, което очаквах:
$VAR1 = { 'abalone' => 'æbәlәuni ', 'abandon' => 'әbændәn', 'abacus' => 'æbәkәs ' }; æbәkәs æbәlәuni әbændәn
Моля, обърнете внимание, че скриптът е записан като UTF-8 кодиране и кодът не трябва да включва никакви utf-8 етикети, тъй като входният и изходният файл са предварително запазени като UTF-8 кодиране.
Накрая отново благодаря на всички вас. И благодаря, @Sinan, за проницателните насоки. Без твоята помощ щях да остана в тъмнината Бог знае колко дълго.
Забележка За да изясня малко повече, ако използвам:
open my $in,'<:utf8',"./hash_test.txt";
open my $out,'>:utf8',"./hash_result.txt";
my %hash = map {split/\t/,$_,2} <$in>;
print $out Dumper(\%hash);
print $out $hash{abacus};
print $out $hash{abalone};
print $out $hash{abandon};
Резултатът е следният:
$VAR1 = { 'abalone' => "\x{e6}b\x{4d9}l\x{4d9}uni ", 'abandon' => "\x{4d9}b\x{e6}nd\x{4d9}n", "\x{feff}abacus" => "\x{e6}b\x{4d9}k\x{4d9}s " }; æbәlәuni әbændәn
И предупредителното съобщение:
Use of uninitialized value in print at C:\hash_test.pl line 13, line 3.
chomp
в картата {} - person Matteo Riva   schedule 19.11.2009' abacus'
във вашия изход на Dumper (което не се виждаше, преди да редактирам публикацията ви). Вижте актуализирания ми отговор. - person Sinan Ünür   schedule 19.11.2009' abacus'
е BOM. - person Sinan Ünür   schedule 19.11.2009