• Publicidad

Problema con acentos en el Windows con print y STDIN

¿Apenas comienzas con Perl? En este foro podrás encontrar y hacer preguntas básicas de Perl con respuestas aptas a tu nivel.

Problema con acentos en el Windows con print y STDIN

Notapor alexsln » 2008-09-08 09:20 @430

Hola foreros.

En primer lugar un saludo, soy nuevo en el foro y no mucho más en Perl.

Me he topado con un problema de novatos (supongo), y no he encontrado la solución en ningún foro.

Estoy creando un script en Perl que, en esencia, captura mediante el STDIN una cadena de texto y luego la guarda en un archivo (en este caso he elegido txt, pero podría ser cualquiera).

Me encuentro que debe haber una incompatibilidad entre la codificación que utiliza Perl y la que utiliza el Command de Windows ya que, los print en los que utilizo caracteres con acentos o eñes, me los cambia por otros símbolos. Y lo mismo ocurre en el proceso inverso, al capturar un texto escrito por la entrada estándar, me estropicia los caracteres con acentos y las eñes.

Como no lo he utilizado mucho, tampoco sé si este es el modo correcto de utilizar un script de Perl (mediante el Command de Windows), así que agradecería cualquier ayuda o consejo que podáis darme.

Como ejemplo al problema, tengo un pequeño script:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
sub capturaNombre($){
  if ($_[0] ne "") {
    print "Variable anterior: ".$_[0]."\n";
    print "Nueva variable: ";
    $_[0]=<STDIN>;
    chop($_[0]);
    capturaNombre($_[0]);
  }
}

$variable = "áéíóú ñ aeiou";
capturaNombre($variable);
 
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4


En él vemos que los caracteres que le paso a través de Perl me los corrompe, pero si le introduzco yo algunos, me los muestra bien.

Bien, pues al almacenarlos, también los corrompe.

¿Qué hago mal?

Un saludo y muchas gracias
alexsln
Perlero nuevo
Perlero nuevo
 
Mensajes: 2
Registrado: 2008-09-08 09:01 @417

Publicidad

Notapor explorer » 2008-09-08 12:05 @545

Bienvenido a los foros de Perl en Español, alexsln.

Una respuesta rápida: tiene que ver que Perl siempre trabaja, por defecto, con la codificación ISO-8859-1, mientras que la consola de Windows está (casi siempre) en la codificación cp850 (la normal en centroeuropa con caracteres multinacionales).

Luego te contesto más... mientras, en estos foros hemos hablado mucho de 'codificación'. Haz una búsqueda.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor explorer » 2008-09-10 02:39 @152

Perdón por la tardanza en responder.

Para la salida de caracteres en la codificación de la consola de Windows, pon esto al principio del programa, antes de cualquier print():
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
binmode(STDOUT, ":encoding(cp850)");
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Lo mismo podrías hacer para STDIN, en caso de leer.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Perfecto

Notapor alexsln » 2008-09-10 04:57 @248

Eso es justo lo que necesitaba. Es perfecto.
¡Gracias! :D
alexsln
Perlero nuevo
Perlero nuevo
 
Mensajes: 2
Registrado: 2008-09-08 09:01 @417

Notapor natxo » 2008-09-11 07:34 @357

explorer escribiste:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
binmode(STDOUT, ":encoding(cp850)");
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


¡Aha!, hace tiempo que esto me fastidiaba en un script. Lo acabo de probar y casi funciona como debiera:

En WinXP:
Código: Seleccionar todo
C:\tmp>ldap.pl -m pep
Pepe Fernández  +34 xxxxxxxxxx


En Linux:
Código: Seleccionar todo
$ ldap.pl -m pep
Pepe Fernández   +34 xxxxxxxxxxx


Así que la localización sí funciona bien en Linux pero no en Windows. Si quito binmode(STDOUT, ":encoding(cp850)"); entonces sale así en Windows:

Código: Seleccionar todo
C:\tmp>ldap.pl -m pep
Pepe Fern├índez  +34 ************


Los datos los sacos de un OpenLDAP, aquí el código:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl
use warnings;
use strict;
use Getopt::Std;


use vars qw/ $opt_e $opt_m $opt_t $opt_w/;
getopts( 'e:t:m:w:?' );

# croak if no valid switches present:
# usage() unless defined($opt_e) or defined($opt_n) or defined($opt_t);
usage() unless defined(($opt_e||$opt_t||$opt_m||$opt_w));

# --- configuration ---
my $ldapserver = "my.server.tld";
my $basedn = "dc=server,dc=tld";
# --- end configuration ---

# if $opt_e we want only attribute mail
# if $opt_t we want attribute homePhone
# if $opt_m we want mobile
# if $opt_w we want work phonenumber

if (defined($opt_e)) {
    search($opt_e,'mail');
}

if (defined($opt_t)) {
    search($opt_t,'homePhone');
}
if (defined($opt_m)) {
    search($opt_m,'mobile');
}
if (defined($opt_w)) {
    search($opt_w,'telephoneNumber');
}
sub search {
use Net::LDAP;
my $ldap = Net::LDAP->new($ldapserver) or die $0;
# at home I do not need binding, otherwise here bind
my $msg = $ldap->search (base   => $basedn,
                        filter  => "(|(cn=*$_[0]*)(uid=*$_[0]*))",
                        attrs   => [$_[1],'cn']);

$msg->code && die $msg->error;

while(my $entry = $msg->shift_entry) {
 my $cn = $entry->get_value('cn');
    next unless (defined($entry->get_value( $_[1] )));
    print "$cn\t$_\n" for $entry->get_value( $_[1] );
}

# $ldap->unbind;
}

sub usage {
my $heredoc = <<EOF;
    usage: $0 [-etmw] name
    -e: get e-mail addres
    -t: get telephone number
    -m: get mobile phone number
    -w: get work phone number
EOF

print $heredoc;
}
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4
natxo
Perlero nuevo
Perlero nuevo
 
Mensajes: 76
Registrado: 2007-08-09 16:22 @723
Ubicación: Países Bajos

Notapor explorer » 2008-09-11 11:03 @502

Lo que no sabemos es en qué codificación están los datos que salen de tu OpenLDAP.

Por la salida que se ve en WinXP, yo diría que están en utf8. Lo que hace el filtrado de la salida hacia cp850 entonces muestra claramente los caracteres utf8 del carácter 'á' en la consola.

En el caso de Linux, me despista un poco más. Si con cp850 sale correcto el carácter, es quizás porque la consola la estás ejecutando en una terminal utf8 (vaya lío... los datos están en utf8, pasan por un filtro cp850 que no hace ningún cambio, y finalmente salen hacia un terminal utf8).

Lo que me despista es si quitas la localización, que sale un carácter típico de la cp850... qué raro...

Con el módulo Encode se pueden pasar los datos de una codificación a otra.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España


Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado