• Publicidad

Problema con backslashes

¿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 backslashes

Notapor carlos » 2006-07-28 04:45 @239

Hola a todos,

Leo de una base de datos un registro que contiene una cadena separada con backslashes '\' y guardo los valores de los subcampos en diferentes variables haciendo un split sobre la cadena. El problema que se me presenta es que cuando algunos subcampos no tienen valor alguno quedan seguidos 2 o mas backslashes y al tratarlos en perl uno de estos desaparece, puesto que perl lo toma como un escape al sigiuiente backslash. (interpolation)
No puedo modificar la cadena (var2) porque la leo de la base datos y no tengo(y no puedo) ninguna forma de modificar la base datos previamente.

Código: Seleccionar todo
use strict;
my ($var1, $var2, $a1, $b2, $c3, $d4, $e5);

# Todos los campos tienen un valor
$var1 = '11\22\33\44\55';  #Esto viene de la base datos y es inmodificable en la base de datos, pero una vez aqui si lo puedo modificar.

($a1,$b2,$c3,$d4,$e5) = split /\\/,$var1;

print "a1=$a1  b2=$b2  c3=$c3  d4=$d4  e5=$e5\n";
# Imprime:  a1=11  b2=22  c3=33  d4=44  e5=55


#Esto viene de la base datos y es inmodificable
#en la base de datos, pero una vez aqui si lo
#puedo modificar. El problema es que no se
#que backslash fue el que desaparecio.
# Por ejemplo, podría tener 11\\\\55 o \\33\\55 o 11\\\\ o ...

# Los campos 3 y 4 estan vacios
$var2 = '11\22\\\55'; 
($a1,$b2,$c3,$d4,$e5) = split /\\/,$var2;

print "a1=$a1  b2=$b2  c3=$c3  d4=$d4  e5=$e5\n";
# Imprime:  a1=11  b2=22  c3=  d4=55  e5=         # Indeseado  >-(
# Yo quiero que imprima
#  a1=11  b2=22  c3=  d4=  e5=55        <-- Deseado - esperado  :-)



Hay alguna forma de "corregir" este efecto por ahora indeseado?

Gracias por su atención.

Carlos Manuel
carlos
Perlero nuevo
Perlero nuevo
 
Mensajes: 1
Registrado: 2005-04-07 05:04 @253

Publicidad

Notapor monoswim » 2006-07-28 07:18 @346

No es recomendable tenés un campo en una base de datos cuyo contenido sena varios campos disitntos, mejor hacer otra tabla con esos campos y referenciarla...

Y luego con left join o inner join traes todo junto en variables separadas...Ahí te ahorrras muchos dolores de cabeza...

Saludos
PD: Sino intenta usar un separador que NUNCA aparezca como valor en los campos...
MonoSwim
Perl Programming Language
Avatar de Usuario
monoswim
Perlero nuevo
Perlero nuevo
 
Mensajes: 452
Registrado: 2003-11-18 16:13 @717
Ubicación: Buenos Aires

Notapor explorer » 2006-07-28 07:34 @357

Supongamos que tenemos un fichero que representará la base de datos. Dentro de él, hay una línea como la siguiente:
Código: Seleccionar todo
11\22\\\55

Si ejecutamos el siguiente código:
Código: Seleccionar todo
#!/usr/bin/perl -l
while ( $var2 = <> ) {
    chomp $var2;            # Quitamos retorno de línea
    print $var2;            # Lo vemos antes..
    @a = split(/\\/,$var2); # Lo dividimos...
    print join("-",@a);     # La sacamos como queda...
}
así: perl programa.pl datos.txt, el resultado es el esperado:
Código: Seleccionar todo
11\22\\\55
11-22---55

Es decir, va todo bien.

¿Cuál es es el problema en tu código?

Resulta que en un programa en Perl, si pones algo entre comillas simples, se supone que Perl debe quedarse con todo ese texto de forma literal... PERO hay dos excepciones a esta regla: el backslash y la propia comilla, que es necesario escaparles.

Así, si tenemos '11\22\\\55', en principio podemos pensar que tenemos justo eso debido a las comillas simples, pero en realidad lo que tenemos es esto: '11\22\\55': un backslash ha desaparecido por haber sido 'escapado' por un hermano suyo. Y por esa razón tu ves en tu programa que entre el 22 y el 55 hay sólo un hueco. Split trabaja bien... no hace ni más ni menos de lo que tu le mandas.

Soluciones... como has visto, yo no he necesito hacer ninguna traducción de la entrada para dárselo diréctamente a split. Si hay algún problema como por ejemplo de que lo recibido es evaluado en algún momento y se pueden perder las barras, una forma de arreglarlo sería transformar esa barras inclinadas en otro carácter más amistoso:
Código: Seleccionar todo
#!/usr/bin/perl -l
while ( $var2 = <> ) {
    chomp $var2;            # Quitamos retorno de línea
    print $var2;            # Lo vemos antes..
    $var2 =~ tr/\\/|/;      # Transformación...
    print $var2;            # Lo vemos antes..
    @a = split(/\|/,$var2); # Lo dividimos...
    print join "-",@a       # La sacamos como queda...
}
con lo que sale:
Código: Seleccionar todo
11\22\\\55
11|22|||55
11-22---55
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: Bing [Bot] y 18 invitados