Tutorial de PERL en castellano : Presentando lo impresentable

Preguntas frecuentemente preguntadas
Bibliografía.
Recursos Internet
Regularizando la situación
Decodificando

Usando subrutinas y secuencias de escape ANSI

Tanto trabajo está acabando con la salud de nuestro político. La campaña electoral está cerca, tiene que inaugurar unas cuantas obras inacabadas todavía, y decide descargarse de un poco de trabajo. Para ello contrata a un militante de base como experto de Informática con cargo a los fondos reservados. Este se encuentra un trabajo ingente, y para empezar decide facilitar un poco su labor escribiendo una utilidad que le permita sacar directorios un poco más monos. Y, ni corto ni perezoso ("Este chico llegará lejos", comenta nuestro político) escribe el programa dir.pl,que aparece en el listado siguiente.


1 #!/usr/bin/perl
2 
3 sub inverso {
4 #Añade la secuencia ANSI de escape para video inverso
return "@_";
6 }
7 
8 sub negrita {
9 #Añade la secuencia ANSI de escape para letra resaltada
10 	return "@_";
11 }
12 
13 sub borra {
14 #Borra pantalla
15 	print  "";
16 }
17 
18 sub normal {
19 #Restablece modo normal
20 	print "";
21 }
22 
23 &borra;
24 $dirSep = "/";				#Solo para MS-DOS
25 
26 
27 if ($ARGV[0] eq "" ) {
28 	$dir = $dirSep;
29 }else {
30 	$dir = $ARGV[0];
31 }
32 
33 #Abre directorio
34 opendir( DIR, $dir );
35 while( $fichero = readdir( DIR ) ) {
36 	push( @ficheros, $fichero );
37 }
38 closedir( DIR);
39 
40 #Cabecera del listado
41 $msg = "Listado del directorio ".&inverso( $dir ); 
42 print "$msg\n";&normal;
43 print "=" x (length($msg) - length(&inverso(""))); print "\n";
44 
45 if ( $dir !~ m!\\$! ) {
46 	$prefijo = $dir.$dirSep;
47 } else {
48 	$prefijo = "$dirSep";
49 }
50 
51 foreach (sort @ficheros ) {
52 	print &inverso( $_ ) if -f "$prefijo$_";
53 	print &negrita( $_ ) if -d "$prefijo$_";
54 	&normal;
55 	print "\n";
56 }
Listado : Programa dir.pl

En este programa ya estamos hablando de palabras mayores. Para empezar, es un poco más largo. Para continuar, es sólo para MS-DOS o Win95, pero se puede adaptar más o menos fácilmente a cualquier otro sistema operativo cambiando el separador de directorios contenido en la variable $dirSep (: para el Mac, / para UNIX). El programa saca un listado del directorio, ordenado en orden alfabético, resaltando los directorios con un tipo de letra más brillante, y los ficheros en video inverso.

Se le llama de la forma siguiente

C:\> perl dir.pl <nombre del directorio>

Si no se da ningún nombre de directorio, toma el directorio raíz; para el directorio actual hay que introducir

perl dir.pl .
.

Veremos primero el truco de sacar las cosas en diferentes tonos, y que se expresan en el programa con extraños signos (para obtener la flechica p'atrás, se pulsa control-P, y sin dejar de pulsarlo, control-[; difícil, pero es así). El programa usa secuencias de escape ANSI, que son órdenes estándar para trabajar con terminales; son tanto aplicables a terminales UNIX (por ejemplo, los tipo vt-100 o ansi), como MS-DOS; en este último habrá que añadir la línea

device=c:\dos\ansi.sys

al fichero config.sys. Con estas secuencias de escape se puede imprimir en diferentes lugares de la pantalla, borrar líneas o la pantalla completa, y cambiar, como aquí, los atributos de partes de la pantalla, todo ello de forma más o menos independiente del sistema. Es algo así como el interfaz gráfico de usuario de los pobres.

El siguiente concepto que introduce este programa es el de subrutinas. Las subrutinas en PERL se pueden declarar en cualquier parte del programa, al principio o al final. Para declararlas, simplemente se precede el nombre de la subrutina con la palabra sub y se le sigue del bloque de instrucciones que se van a ejecutar. Pueden no utilizar parámetros (como borra y normal). En este caso se llaman precediéndo el nombre con el símbolo &, o bien escribiendo do borra. También se puede llamar a una subrutina con parámetros, en cuyo caso forman todos parte de la matriz @_, como se ve por ejemplo en la subrutina negrita. Los elementos de esta matriz son, como es natural, $_[0], $_[1] y así sucesivamente, aunque se pueden asignar todos de una vez a parámetros locales de la subrutina, de esta formalocal($zipi, $zape) = @_;En esta sentencia se declaran simultáneamente $zipi y $zape como variables locales y se les asignan los dos primeros parámetros que se le han pasado a la subrutina. Si no se declararan como local, las variables serían visibles por todo el programa, como sucede en el resto de las variables en PERL.

[v5]En realidad, local crea variables globales pero con valores locales; es decir, se crea una variable que se puede ver en todo el programa, pero cuyo valor se guarda al principio de la subrutina y se recupera al final de la subrutina. En la versión 5 se introduce la palabra clave my, que declara verdaderas variables locales. En la versión 5, por tanto, se suele preferir my para declarar las variables de las subrutinas. [/v5]

La lectura del directorio se hace a partir de la línea 31; para eso utiliza funciones similares a las que hay en C o Pascal; una funcion, opendir, "abre" el directorio, y las otras van leyendo secuencialmente los nombres de todos los ficheros de ese directorio y metiéndolos en la matriz @ficheros.

-e Comprueba si el fichero existe o no
-f Comprueba si es un fichero normal
-d Comprueba si es un directorio
-T/-B Comprueba si es de texto o binario. Pero no funcionan fuera de Linux.
Tabla : Operadores de comprobación de ficheros

Luego, a partir de la línea 49, y utilizando los operadores -f y -d, que comprueban si el fichero cuyo nombre viene después es un fichero normal o un directorio, se va imprimiendo con los atributos correspondientes. Estos son un ejemplo de los operadores de fichero que se utilizan mucho en PERL (ver la tabla 4), y que vienen heredados de comandos similares en los shell de UNIX (como csh y bash), nosotros tenemos la suerte de poder usarlos en ms-dos también. Otros operadores figuran en la tabla 4.

[ Preguntas frecuentemente preguntadas] [ Bibliografía.] [ Recursos Internet] [ Regularizando la situación] [ Decodificando]