miércoles, febrero 10, 2010

Pequeños fallos de Perl


Perl me gusta mucho, pero a veces tiene cosas que te pueden volver loco.

Hoy quería sacar un listado a partir de la salida del comando cacls en un servidor Windows. Era un servidor que ofrece una carpeta compartida. Este comando sirve entre otras cosas para obtener un fichero con todas las carpetas y ficheros de una unidad y los usuarios que tienen permisos de acceso.

La especialidad del lenguaje Perl es el tratamiento de ficheros de texto para listados. Recordad que PERL se ha asociado en algunos momentos a Practical Extraction and Report Language. Vamos, que es el lenguaje adecuado para lo que quería.

En 1998 compré un libro de PERL5 llamado "Perl al descubierto".
En ese libro explicaban la forma de utilizar la función split de la siguiente forma:

"La función split se usa para separar los elementos que es´tan en la cadena $cita y ponerlos en el arrray @palabras":

@palabras = split(' ',$cita);

A ver, en condiciones "normales" la cosa funciona bien, pero yo quería separar las líneas del fichero por un texto que incluía un carácter especial que era la contrabarra: \

Pues os puedo asegurar que la contrabarra no iba ni por el forro. Lógicamente al ser un carácter especial para Perl, hay que poner por delante otra contrabarra (dos contrabarras). La cosa más o menos era así:

@cachos = split(' texto1\\texto2',$linea);

Pues esto no funciona. Tanto en la versión vieja del curro, como en mi mac mini el error es parecido: "Trailing \ in regex m/\/ at cachos.pl line 2". (regex se refiere a Regular Expresion).

En Perl, cuando se utilizan cadenas en expresiones regulares hay que utilizar las dobles comillas en lugar de la comilla simple. Sobre todo es imprescindible lo de las comillas dobles para que reconozca los caracteres especiales. Pero la siguiente instrucción devuelve exactamente el mismo error:

@cachos = split("texto1\\texto2",$linea);

Al final, buscando en la red, que era lo primero que tenía que haber hecho, encuentro la solución que es una sintaxis diferente de la misma función:

@cachos = split(/texto1\\texto2/, $linea);

La versión de Perl utilizada en el servidor era la 5.8.0. La versión de Perl de mi mini mac (Mac OSX Leopard comprado el año pasado) es 5.8.8. (¡¡¡En 10 años casi no ha evolucionado!!!). Los resultados han sido iguales tanto en el servidor como en el mac OSX.

Si se mantiene la anterior sintaxis por compatibilidad hacia atrás, el interprete podría haber mostrado un warning como hacen otros lenguajes.

Si se mantiene para tener diferentes formas de llamada a esa función, pues muy bien, pero que la funcionalidad ofrecida sea la misma en los dos casos.

Saludos.

3 comentarios:

Francisco Oca dijo...

A mi me pasaba esto mismo en C#.

Yo probaría con 4 barras invertidas.

Hay que distinguir entre el carácter de escape de las cadena de perl y el carácter de escape de las expresiones regulares.

Una expresión regular también usa el carácter de escape \ para por ejemplo decir que espera un punto: \.

Entonces podría ocurrir que cuando tu pones en la cadena dos barras invertidas se le pasa 1 barra invertida al analizador de expresiones regulares y te diga que esperaba un carácter después de la barra invertida. No estoy nada seguro...

Un saludo!

Aitor Iriarte dijo...

Hombre Thor!
Qué honor tenerte como comentarista.

Para el que no lo sepa, como el propio nombre del software indica, aquí está el autor de la Foca y además mencionado en el hall-of-fame del maligno como experto troyanista.

Que sepas que el foro privado que mencionaste una vez en tu blog guarda total similitud con el grupo al que pertenece Lisbeth Salander de Millenium. Pero que nadie se confunda creo que es de sombrero blanco :-)

Respecto al tema Perl al final funcionaba con la doble contrabarra entre barras. He hecho la prueba con cuatro contrabarras y entonces busca dobles barras para el split. Bueno, que esto parece un trabalenguas.

Saludos.

Francisco Oca dijo...

Jeje se agradecen los halagos. Pero no se tanto como crees. Para empezar no se Perl :P

Y de troyanos lo básico, cualquier reverser me da 1000 vueltas.

Saludos!