Vie Jul 28, 2006 3:45 am
|
 |
carlos
Perlero Nuevo

|
Registrado: 07 Abr 2005
Mensajes: 3
|
|
| Problema con backslashes |
|
|
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: |
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 |
|
|
|

Vie Jul 28, 2006 6:18 am
|
 |
monoswim
Vive para Perl en Español

|
Registrado: 18 Nov 2003
Mensajes: 716
Ubicación: Buenos Aires
|
|
|
|
|
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... |
|

Vie Jul 28, 2006 6:34 am
|
 |
explorer
Moderador

|
Registrado: 24 Jul 2005
Mensajes: 4084
Ubicación: Valladolid, España
|
|
|
|
|
Supongamos que tenemos un fichero que representará la base de datos. Dentro de él, hay una línea como la siguiente:
Si ejecutamos el siguiente código:
| Código: |
#!/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: |
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: |
#!/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: |
11\22\\\55
11|22|||55
11-22---55 |
|
|

Powered by phpBB © 2001, 2005 phpBB Group
|