Как можно угадать кодировку строки в Perl?
У меня есть строка Unicode и не знаю, какова ее кодировка. Когда эта строка считывается программой Perl, есть ли кодировка по умолчанию, которую Perl будет использовать? Если да, то как я могу узнать, что это такое?
Я пытаюсь избавиться от символов, отличных от ASCII, от ввода. Я нашел это на каком-то форуме, который это сделает.
my $line = encode('ascii', normalize('KD', $myutf), sub {$_[0] = ''});
Как это будет работать, если не указано кодирование ввода? Должен ли он быть указан так?
my $line = encode('ascii', normalize('KD', decode($myutf, 'input-encoding'), sub {$_[0] = ''});
Ответы
Ответ 1
Чтобы узнать, в какой кодировке используется что-то неизвестное, вам просто нужно попробовать и посмотреть. Модули Encode:: Detect и Encode::Guess автоматизируют это, (Если у вас возникли проблемы с компиляцией Encode:: Detect, попробуйте использовать его fork Encode::Detective.)
use Encode::Detect::Detector;
my $unknown = "\x{54}\x{68}\x{69}\x{73}\x{20}\x{79}\x{65}\x{61}\x{72}\x{20}".
"\x{49}\x{20}\x{77}\x{65}\x{6e}\x{74}\x{20}\x{74}\x{6f}\x{20}".
"\x{b1}\x{b1}\x{be}\x{a9}\x{20}\x{50}\x{65}\x{72}\x{6c}\x{20}".
"\x{77}\x{6f}\x{72}\x{6b}\x{73}\x{68}\x{6f}\x{70}\x{2e}";
my $encoding_name = Encode::Detect::Detector::detect($unknown);
print $encoding_name; # gb18030
use Encode;
my $string = decode($encoding_name, $unknown);
Я нахожу, что encode 'ascii'
является хромым решением для избавления от символов, отличных от ASCII. Все будет заменено вопросительными знаками; это слишком мало, чтобы быть полезным.
# Bad example; don't do this.
use utf8;
use Encode;
my $string = 'This year I went to 北京 Perl workshop.';
print encode('ascii', $string); # This year I went to ?? Perl workshop.
Если вы хотите читать ASCII-текст, я рекомендую вместо этого Text:: Unidecode. Это тоже кодировка с потерями, но не такая страшная, как обычная encode
выше.
use utf8;
use Text::Unidecode;
my $string = 'This year I went to 北京 Perl workshop.';
print unidecode($string); # This year I went to Bei Jing Perl workshop.
Однако, избегайте этих кодировок с потерями, если вы можете им помочь. Если вы захотите изменить операцию позже, выберите либо один из PERLQQ
или XMLCREF
.
use utf8;
use Encode qw(encode PERLQQ XMLCREF);
my $string = 'This year I went to 北京 Perl workshop.';
print encode('ascii', $string, PERLQQ); # This year I went to \x{5317}\x{4eac} Perl workshop.
print encode('ascii', $string, XMLCREF); # This year I went to 北京 Perl workshop.
Ответ 2
Модуль Encode позволяет вам это сделать. Вы decode
необработанные октеты с тем, что, по вашему мнению, является кодировкой. Если октеты не представляют действительную кодировку, она взрывается, и вы поймаете ее с помощью eval. В противном случае вы вернете правильно закодированную строку. Например:
use Encode;
my $a_with_ring =
eval { decode( 'UTF-8', "\x6b\xc5", Encode::FB_CROAK ) }
or die "Could not decode string: [email protected]";
Это имеет тот недостаток, что одна и та же последовательность октетов может быть действительной при нескольких кодировках
У меня есть еще об этом в следующем Эффективном программировании на Perl, 2nd Edition, в котором есть целая глава по работе с Unicode. Я думаю, что мой издатель разозлится, если я разместил все это.:)
Вы также можете увидеть Juerd Unicode Advice, а также некоторые из документов Unicode, которые поставляются с Perl.
Ответ 3
Вы также можете использовать следующий код для шифрования и дешифрования кода
sub ENCRYPT_DECRYPT() {
my $Str_Message=$_[0];
my $Len_Str_Message=length($Str_Message);
my $Str_Encrypted_Message="";
for (my $Position = 0;$Position<$Len_Str_Message;$Position++){
my $Key_To_Use = (($Len_Str_Message+$Position)+1);
$Key_To_Use =(255+$Key_To_Use) % 255;
my $Byte_To_Be_Encrypted = substr($Str_Message, $Position, 1);
my $Ascii_Num_Byte_To_Encrypt = ord($Byte_To_Be_Encrypted);
my $Xored_Byte = $Ascii_Num_Byte_To_Encrypt ^ $Key_To_Use;
my $Encrypted_Byte = chr($Xored_Byte);
$Str_Encrypted_Message .= $Encrypted_Byte;
}
return $Str_Encrypted_Message;
}
my $var=&ENCRYPT_DECRYPT("hai");
print &ENCRYPT_DECRYPT($var);