2009-12-28 23 views
22

Tengo una cadena Unicode y no sé cuál es su codificación. Cuando una cadena es leída por un programa Perl, ¿hay una codificación predeterminada que usará Perl? Si es así, ¿cómo puedo averiguar qué es?¿Cómo puedo adivinar la codificación de una cadena en Perl?

Estoy tratando de deshacerme de los caracteres no ASCII de la entrada. He encontrado esto en algún foro que lo hará

my $line = encode('ascii', normalize('KD', $myutf), sub {$_[0] = ''}); 

¿Cómo este trabajo anterior cuando no se especifica la codificación de entrada? ¿Debería especificarse así?

my $line = encode('ascii', normalize('KD', decode($myutf, 'input-encoding'), sub {$_[0] = ''}); 
+1

corrígeme si me equivoco, pero pensé que todo el punto de Unicode es que no tiene una "codificación" - todo está allí. –

+3

No tiene una cadena Unicode. Tiene un archivo lleno de bytes que representa una cadena Unicode en alguna codificación. Si no conoce la codificación del archivo, luego busque un marcador de orden de bytes al comienzo del archivo. Si no hay una lista de materiales, no tienes suerte. –

+0

Parece que está haciendo al menos dos preguntas separadas (1er y 2do párrafo). – Amnon

Respuesta

29

Para saber en qué codificación utiliza algo desconocido, solo tiene que intentarlo. Los módulos Encode::Detect y Encode::Guess automatizan eso. (Si tiene problemas para compilar Codificar :: Detect, intente su tenedor Encode::Detective en su lugar.)

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); 

encuentro encode 'ascii' es una solución cojo para deshacerse de caracteres no ASCII. Todo será sustituido con signos de interrogación; esto es demasiado siniestro para ser útil.

# 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. 

Si desea que el texto ASCII legible, recomiendo Text::Unidecode lugar. Esto también es una codificación con pérdida, pero no tan terrible como el encode anterior.

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. 

Sin embargo, evite esas codificaciones con pérdida si puede evitarlo. En caso de que desee revertir la operación más tarde, elija cualquiera de PERLQQ o 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. 
+0

La entrada que recibo siempre usa el conjunto de caracteres latinos. La función de normalización que uso convertiría "Café" en "Cafe". Sin embargo, esto no funciona en todos los casos. Teniendo esto en cuenta, ¿preferiría seguir utilizando el método PERLQQ o XMLCREF? – Maulin

+0

No importa lo que prefiera; después de todo, es su código y responsabilidad, y solo usted conoce todas las circunstancias. Si de verdad está contento con Café → Cafe, entonces reemplace su función personalizada con 'Text :: Unidecode'. Eso funciona en todos los casos. – daxim

+0

Gracias. Creo que intentaré eso. – Maulin

3

Encode El módulo tiene una forma que se puede tratar de hacer esto. Usted decode octetos brutos con lo que cree que es la codificación. Si los octetos no representan una codificación válida, esta explota y la pescas con una evaluación. De lo contrario, obtendrás una cadena codificada correctamente. Por ejemplo:

use Encode; 

my $a_with_ring = 
    eval { decode('UTF-8', "\x6b\xc5", Encode::FB_CROAK) } 
    or die "Could not decode string: [email protected]"; 

Esto tiene el inconveniente de que la misma secuencia de octetos puede ser válido en múltiples codificaciones

tengo más que decir acerca de esto en la próxima Effective Perl Programming, 2nd Edition, que tiene un capítulo completo sobre cómo tratar con Unicode . Creo que mi editor se enojaría si publicara todo. :)

Es posible que también desee ver Juerd's Unicode Advice, así como algunos de los documentos Unicode que vienen con Perl.

-4

Usted puede utilizar el código siguiente también, para cifrar y descifrar el código

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); 
+0

La pregunta era sobre codificaciones de texto, y no sobre cifrado. – Flimm

Cuestiones relacionadas