miércoles, 16 de junio de 2010

martes, 8 de junio de 2010

Perl Tutorial 3 - Variables



BIENVENIDOS A PROGRAMACION PERL

Perl Video Tutorial - Part 1 - Installing ActivePerl 5.8.8



BIENVENIDOS A PROGRAMACION PERL

Análisis de un lenguaje de programación Perl



BIENVENIDOS A PROGRAMACION PERL

tutorial de perl

¿Qué es?
Definiciones básicas de Perl
Perl significa Practical Extraction and Report Language, algo así como lenguaje práctico de extracción y de informes. Es un lenguaje creado por Larry Wall (quien, por
cierto, es uno de los net.gods más conocidos en la actualidad) con el objetivo principal de simplificar las tareas de administración de un sistema UNIX; en realidad hoy
en día (en su versión 5.005, y posiblemente pronto, la 5.6) se ha convertido en un lenguaje de propósito general, y una de las principales herramientas de un buen
internetero y de un buen webmaster.
Larry Wall es el tipo de personas que han hecho de la Internet lo que es ahora: un lugar con libre intercambio de ideas, donde los que saben de algo, los gurus, ayudan al
que no sabe. Larry (larry@wall.org) solía ser un habitual del grupo de usenet comp.lang.perl, y era habitual que el propio Larry contestara a una pregunta de un
principiante o a un error con un parche para solucionarlo. Hoy en día, desgraciadamente, ya no es tan común, porque el esfuerzo de trabajar con la comunidad Perl es tal
que no le deja mucho tiempo.
Perl es un lenguaje que hereda ciertas estructuras de los intérpretes de comandos de UNIX, especialmente el csh, y de otras utilidades estándar, como awk y sed. Aparte
de esto, está diseñado para hacer todo lo que hacen cualquiera de ellos y todos ellos juntos, y la mayoría de las veces de forma más simple, comprensible y fácil de
depurar (aunque algunas veces no muy fácil de entender). Si alguna vez habeis tratado de escribir un script para el shell, sabéis lo que quiero decir.
Perl es un lenguaje interpretado, aunque en realidad, el intérprete de Perl, como todos los intérpretes modernos, compila los programas antes de ejecutarlos. Por eso se
habla de scripts, y no de programas, concepto referido principalmente a programas compilados al lenguaje máquina nativo del ordenador y sistema operativo en el que se
ejecuta.
El mejor libro de referencia sobre el
Perl es Programming Perl, por Larry
Wall y otros (llamado el libro del
camello por razones obvias). Aparte
de la referencia, vienen ejemplos,
reglas de estilo, y es bastante
divertido.
A pesar de que la versión actual del intérprete de Perl es la 5, a veces se puede uno encontrar la versión 4.036, el último patchlevel de la versión 4 y probablemente el
más estable. Actualmente, en enero del 2003, la versión estable es la 5.8, con una nueva versión 6 en desarrollo que va a ser la caña de España, pero que todavía se hará
de esperar un cierto tiempo. La versión 5 es prácticamente compatible 100% con la 4; virtualmente todos los scripts que funcionan para la versión 4 lo hacen también en
la 5. La mayor parte de los scripts presentados en este tutorial están desarrollados para la versión 4 (porque las primeras versiones de este tutorial son del año 94), pero
deberían de funcionar, en principio, para la versión 5 o cualquier otra versión. Cuando son para la versión 5 de Perl, se indicará explícitamente con este signo v5.
Aunque desarrollado originalmente en un entorno UNIX, actualmente hay versiones para casi todos los sistemas operativos: Windows XP, Amiga, MacOS (ver
Bibliografía/Recursos.). Los scripts son compatibles entre las diversas plataformas, de forma que es un verdadero lenguaje multiplataforma. Muchos fabricantes lo
incluyen en sus versiones de UNIX; también el Linux lo incluye. Si quieres saber si está en tu UNIX, escribe simplemente
UNIX% which perl
/usr/local/bin/perl
y si contesta algo similar a lo anterior, es que está instalado en el sistema. En algún otro "sistema operativo", como Windows xx, acuérdate de si lo instalaste o no, debe
de estar en algún lado en tu disco duro. Para bajarte la última versión, consultar el apartado de enlaces
Breve historia del lenguaje PERL
De cómo partiendo de la nada, se llegó a las cimas más altas de la miseria
La primera versión de PERL que llegó a ser suficientemente conocida fue la versión 4, dada a conocer al mundo por el libro del camello . Esta versión se estuvo
desarrollando desde 1991 a 1993, y coincidió con la popularidad del PERL como lenguaje para programación de servidores de Internet; aunque originalmente se había
diseñado como lenguaje para administración de sistemas.
La versión 5 estable no apareció hasta octubre de 1994, y ha sido tan popular que todavía se usa. Introdujo muchas de las características que hacen al PERL tan fácil de
programar, incluyendo los módulos, las facilidades para programación dirigida a objetos, referencias y mucho mejor documentación. Aparecen muchos otros libros, tales
como Learning Perl.
A partir de la versión 5.6, Perl sufrió una nueva transformación (comenzando por la eliminación de muchos números en sus versiones). Además, se incluye
soporte pleno de caracteres internacionales, hebras, y mejor compilador. Se institucionaliza un sistema de patch pumpkin, o encargado de cada nueva versión,
que es el que decide qué va a entrar de nuevo y qué no, sustituyendo a Larry Wall. Una empresa comercial, ActiveState, que ya participaba activamente en su
desarrollo, comienza a controlar más de cerca al PERL, y a la vez, a crear herramientas más potentes (y comerciales) para desarrollo con PERL
Tutorial de Perl: Índice file:///home/jmerelo/txt/tutoperl2000/tutorial-print.html
2 of 20 13/02/03 12:48
A partir del año 2000, se empieza a discutir sobre la nueva versión, la 6, que será un gran salto sobre la versión anterior, pero todavía no está muy claro qué es lo que
va a ser. Aparte de más rápida, más flexible y todo eso, todavía no se ha comenzado su desarrollo.
Una referencia mucho más completa se puede encontrar en la línea temporal de PERL.
¿Para qué sirve?
Aplicaciones del lenguaje Perl
Prácticamente, sirve para todo. Todas las tareas de administración de UNIX se pueden simplificar con un programa en Perl. Se usa también para tratamiento y
generación de ficheros de texto. También hay proyectos completos y complejos escritos en Perl, pero son los menos.
La forma del lenguaje facilita la programación rápida y sucia , el hacer un programa rápido para que funcione. Esto hace también que se utilice para hacer prototipos
rápidos de algún algoritmo que queremos ver funcionar antes que tomarnos la molestia de programarlo en un lenguaje más eficiente, como el c++. Y últimamente ha
encontrado su aplicación en la escritura de CGI (common gateway interface), o scripts ejecutados desde páginas de la World Wide Web. La mayoría de los programas
que se encuentra uno para procesar formularios en la Internet llevan la extensión .pl, lo cual denota que están escritos en Perl.
En general, los programas en Perl se ejecutan en el servidor, como todos los programas CGI, a diferencia de otros programas ejecutados por el cliente (generalmente un
navegador como el Internet Explorer de Microchof o el Navigator), como aquellos escritos en JavaScript o Java. Existen además extensiones al Apache (mod_perl) que
permiten ejecutar directamente programas en Perl desde el servidor de HTTP.
Mediante una serie de módulos adicionales, tales como el DBD o el ODBC, Perl puede servir para acceder a bases de datos, desde BD gratuitas como MySQL hasta el
Microsoft SQL server usando ODBC. Por supuesto, esto se puede combinar con un CGI para hacer aplicaciones tales como un carrito de la compra para un sitio web.
Pero esto se deja como ejercicio para el lector.
¿Cómo se usa?
Cómo conseguir e instalar programas en Perl
Primero, hay que bajarse e instalar alguna versión de Perl. Hay versiones para casi todos los sistemas operativos, o sea que no debería de ser complicado. Es conveniente
consultar la sección de enlaces, para ver dónde podemos conseguirlo.
En todo caso, lo más probable es que si tienes una distribución de Linux más o menos decente, tal como RedHat , SuSE o Debian, venga ya incluido. Consulta los
paquetes que tienes instalados (usando la herramienta correspondiente) o simplemente escribe:
bash$ which perl
/usr/bin/perl
Si contesta algo así como lo anterior, es que está instalado (y si quieres nota, escribe
bash$ perl -v
This is perl, v5.8.0 built for i386-linux-thread-multi
Copyright 1987-2002, Larry Wall
Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.
Complete documentation for Perl, including FAQ lists, should be found on
this system using ’man perl’ or ’perldoc perl’. If you have access to the
Internet, point your browser at http://www.perl.com/, the Perl Home Page.
lo que, como ves, te devuelve la versión, e información adicional.
En Windows, como siempre, es otro cantar. Sin embargo, hay una excelente versión de Perl para Windows, de la empresa ActiveState. No hay más que bajárselo, pulsar
en el icono de SetUp correspondiente, y se lanza un procedimiento de instalación similar al de todos los programas. Desde ese momento, ya se puede usar desde la línea
de comandos.
En MSDOS (¿hay alguien que todavía use MSDOS?), basta descomprimirlo, y añadir al PATH el directorio donde se encuentra perl.exe.
En otros sistemas operativos, seguir el procedimiento respectivo en caso de que exista una versión ya compilada, pero puede que no exista una versión binaria. Habrá
entonces que bajarse los fuentes de alguno de los sitios web existentes, y luego compilarlos usando los siguientes comandos (si es que es un SO parecido a UNIX:
sh Configure
make
make test
make install
Para más información, consultar el fichero INSTALL o perldoc INSTALL que viene con los fuentes (malamente podrás usar perldoc si no tienes instalado Perl, pero en
fin...).
Mi primer programa en Perl
Cómo escribir y ejecutar un programa simple Perl
Escribir el archiconocido "Hola" en Perl no puede ser más fácil:
print "Passa, tio\n";
Y eso es todo. No hay necesidad de abrir el programa, ni de cerrarlo, ni de incluir librerías estándar o no, ni nada de nada. Solamente hay que tener cuidado de terminar
todas las sentencias con;. \n, que se suele leer "escape-N", tiene el mismo significado que en C; es decir, un retorno de carro.
Ejecutarlo es otro cantar; o mejor dicho, muchos cantares, una cantata entera. El Perl siempre Hay Muchas Formas de Hacer Las CosasTM. Al menos tres, en este caso.
Guarda el programa en un fichero, llamémoslo passa.pl. Se puede ejecutar con
C:\PROGS\Perl>perl passa.pl
Passa, tio
Tutorial de Perl: Índice file:///home/jmerelo/txt/tutoperl2000/tutorial-print.html
3 of 20 13/02/03 12:48
Todo esto suponiendo que Perl esté en el PATH de ejecución, claro está.
Pasa de guardar el programa en un fichero y ejecútalo directamente. Se le da el switch-e al intérprete para indicar que se debe ejecutar el script que viene a
continuación (y ojo con las comillas)
C:\PROGS\PERL>perl -e ’print "Passa, tio\n";’
Passa, tio
Si estás en UNIX, se utiliza una sintaxis similar a los scripts del intérprete de comandos, es decir, guardar el fichero con una primera línea que indica dónde está
el intérprete que va a ejecutar el resto del fichero. En el caso del Perl, puede ser algo como #!/usr/local/bin/perl, o #!/usr/bin/perl en RedHat Linux, por
ejemplo) (los símbolos iniciales se suelen denominar pound-bang, o almohadilla-admiración, en román paladino). En todo caso, habrá que sustituirlo por el
camino completo donde habita el intérprete de Perl (si no se sabe, recurre al comando de UNIXwhich (como hemos visto antes), o, por último, al operador de tu
sistema; ahora, que si tú mismo eres el operador de tu sistema y no sabes como hacerlo, tienes un problema, tío... Bueno, siempre te queda la internet). Tras salvar
el fichero, habrá que dar la orden
UNIX% chmod +x passa.pl
para convertirlo en ejecutable; hecho eso, se puede ejecutar directamente escribiendo
UNIX% passa.pl
Passa, tio
En Windows y familia, hay al menos dos formas de hacerloTM(suponiendo, claro está, que le pille de buenas y te deje hacer algo). Tras instalar la versión de Perl
para WinXX de la Internet, de la empresa ActiveState, se crea un acceso directo a perl.exe y se copia al directorio \Windows\SendTo; esto hará que aparezca Perl
dentro del menú enviar a, que es una de las opciones del menú que surge al pulsar con el botón derecho del ratón.
Otra forma es más específica para ficheros de tipo .pl, y es el mismo mecanismo que se usa para asignar iconos y programas ejecutables a los ficheros no
ejecutables: en la carpeta MiPC, pasar a Ver - Opciones y pulsar sobre la pestaña Tipos de Archivo: Se crea un nuevo tipo que sean "Programas en Perl", y se le
pueden asignar acciones como edición o ejecución; de esta forma, con sólo pulsar dos veces sobre el icono, se ejecuta el programa.
Para trabajar con Perl en
Windows, se puede ver
Automating Windows with
PERL, por Scott McMahan .
Para editar un programa en Perl, lo más adecuado es conseguir un editor para programadores, porque el lenguaje no incluye un entorno integrado de programación. Lo
más parecido a tal entorno integrado, tanto en Win95/NT como en UNIX, es el emacs, puesto que tiene un modo Perl de edición, que tiene en cuenta indentaciones y
otras particularidades de su sintaxis, como el emparejamiento de paréntesis y llaves y los comentarios, y asigna diferente color a las palabras dependiendo del contexto.
Otra opción con unos pocos menos megas puede ser cualquier editor de programador con diferentes opciones dependiendo de la extensión del programa, como el
Programmer´s File Editor . Aunque, por supuesto, si puedes conseguirte el emacs para Windows, es con diferencia lo mejor.
Más difícil todavía
Variables, interpolación y cadenas
Ya que hemos hecho nuestro primer programa, vamos a por el segundo. Supongamos que somos un político corrupto cualquiera, y que, dado el alto número de
transacciones diarias por las cuales cobramos comisiones ilegales, decidimos escribir un programa enPERL que nos resuelva la difícil papeleta de calcularlas sobre la
marcha. Ni cortos ni perezosos, nos puede servir lo siguiente (comile.pl):
Tutorial de Perl: Índice file:///home/jmerelo/txt/tutoperl2000/tutorial-print.html
4 of 20 13/02/03 12:48
Listado : Programa comile.pl
print "Valor del inmueble? ";
$valor = ;
$comision = $valor * 0.25;
print "Comision = $comision\n";
que da el resultado siguiente
C:\PROGS\PERL>perl comile.pl
Valor del inmueble 1000000 [Escrito por el usuario]
Comision = 250000
A partir de este momento, indicaremos en rojo las palabras clave de PERL, en verde las variables de PERL y en azul las órdenes de control.
En este ejemplo hay algunos elementos más de PERL. Como se ve, las variables se indican con un símbolo de $ (sumamente indicado para el ejemplo); en este caso se
trata de variables escalares, que contienen un valor numérico o una cadena; a PERLle da exactamente igual que se trate de uno o de otro, la transformación se hace
automáticamente. Y no hace falta ninguna declaración de variables; cada variable se declara en el momento que se usa, y si no se ha usado anteriormente, aparece
automáticamente con el valor 0 o ´´ (cadena nula). Las variables en PERL tienen todas visibilidad global, si no se dice lo contrario.
El programa pide además, la intervención del usuario, leyendo en una variable lo que éste teclea. Para ello se utiliza un filehandle o puntero a un fichero abierto (el
equivalente a un FILE* en C), que está disponible en todos los programas, la entrada estándar o stdin (estandard input); de la misma manera, también existe la salida
estándar o stdout, es decir, que es lo mismo print STDOUT que print). El nombre de esta variable no está precedido por ningún símbolo de $ para indicar que se trata de
un filehandle, o una variable que representa un fichero. Los angle brackets, o paréntesis angulares <>, indican que se lee del fichero una línea completa, hasta que el que
teclea pulsa un retorno de carro.
Por último, se está utilizando la operación denominada interpolación de variables. Una variable incluida dentro de una cadena entre comillas dobles será sustituida por
su valor (no en el caso de tratarse de comillas simples).
Dando vueltas sobre lo mismo
Bucles, lectura de teclado y ficheros
Cuando, tras las elecciones, nuestro político corrupto sale reelegido por méritos propios, viene inmediatamente la recuperación económica y con ello el boom
inmobiliario (favorecido por la recalificación en terrenos construibles de los parques de la ciudad). Tantas comisiones tiene que calcular, que decide escribir un programa
que lo haga continuamente, en vez de tener que ejecutar el programa anterior cada vez. Decide además guardar detalles de todo en un fichero, que llevará en un disquete
escondido en el collar del perro, para que, en caso de que lo investigue una comisión del Congreso, pueda tirar de la manta tecnológicamente. Saldría entonces algo como
lo incluido en el listado siguiente:
Listado : Programa manta.pl
#!/usr/bin/perl
open( MANTA, ">clientes");
while(1){
print "Cliente\n";
chop( $paganini = );
last if !$paganini;
print "Valor inmueble\n";
chop( $valor= );
$comision = $valor * 0.25;
print "Comision = $comision\n";
print MANTA "$paganini $comision\n";
}
close MANTA;
En este segundo programa, que llamaremos manta.pl, se introducen algunos conceptos nuevos más. Para empezar, se utiliza la orden open para abrir un fichero; a esta
orden se le dan dos parámetros, el filehandle por el cual nos vamos a referir al fichero en lo sucesivo, y una cadena que incluye el nombre del fichero y la forma de
manejar ese fichero. En este caso, se usa la expresión ">clientes", que indica que se va a abrir para escritura. Otras opciones son las que aparecen en la tabla 1. Si no se
pone nada, se supone que el fichero se abre para lectura. Y esto es fuente de continuas confusiones.
Como siempre, hay Más de Una Forma de Hacerlo TM, aunque no necesarimente más corta. Se puede meter el nombre del fichero en una variable tal como $MANTA, y
abrirlo de la forma siguiente:
$MANTA=’>prueba’;
open MANTA;
Es decir, cuando no se pone una cadena detrás del filehandle, se usa el contenido de una variable que tenga el mismo nombre. Véase también que en este caso no he
usado paréntesis detrás de open; son opcionales. Hay muchas más cosas sobre open leyendo el tutorial incluido en la documentación, se accede a él escribiendo
perldoc perlopentut o man perlopentut.
Tabla : Modos de apertura de ficheros
> Abrir para escritura
>> Abrir para concatenar
< Abrir para lectura
>+ Abrir para lectura/escritura
¦ orden
Ejecutar un programa que filtrará lo que
se imprima en el fichero.
orden |
Ejecutar una orden, de la cual se leerá la
salida.
A continuación se comienza un bucle con la ordenwhile, que se ejecutará mientras la expresión entre paréntesis sea cierta, o sea, en este caso, en principio, siempre. Los
valores "verdaderos" se indican en Perl con un número distinto de 0 o una cadena no nula. Tras while va siempre un bloque, que se comienza y termina con llaves. Dado
que es un bloque, y no la alternativa orden|bloque (como sucede, por ejemplo, en el lenguaje C), se tendrán que utilizar siempre las llaves, aunque se trate de un solo
Tutorial de Perl: Índice file:///home/jmerelo/txt/tutoperl2000/tutorial-print.html
5 of 20 13/02/03 12:48
comando. También se podría sustituir esta línea por until(0) {que tendría exactamente el mismo significado (recuerda, Hay Más De Una Forma de Hacerlo). O por dos
o tres formas más, al menos.
En la línea 4 se hacen dos cosas juntas: se asigna a una variable lo que introduce el usuario, y a esta variable se le elimina el último carácter ( chop, que significa trocear,
como en el chopped). Esto es necesario porque, a diferencia de otros lenguajes, Perl incluye el retorno de carro en la cadena que lee. Lo eliminamos entonces para que
quede todo bonito.
Tabla : Tipos de bucles en Perl
ETIQUETA while (EXPR) BLOQUE
ETIQUETA while (EXPR) BLOQUE continue BLOQUE
ETIQUETA for (EXPR;EXPR;EXPR) BLOQUE
ETIQUETA foreach VAR (MATRIZ) BLOQUE
En la línea 5 se utiliza una construcción típica:
Perl .
En este caso, se sale del bucle (last) en caso de que lo que se haya leido sea la cadena vacía (recordad que previamente hemos eliminado el retorno de carro). Esta línea
se podía haber sustituido por la siguientelast unless $paganini;que tiene exactamente el mismo significado (unless significa a menos que); en general, una sentencia en
la que se utiliza if con una expresión verdadera se puede sustituir por otra en la que se utiliza unless con la misma expresión negada. Otras expresiones que regulan
bucles son next, que ejecuta la iteración siguiente sin pasar por el resto de las órdenes del bucle, y redo, que vuelve a comenzar el bucle sin evaluar la condición.
Tabla : operadores de cadenas en Perl
lt, gt, le, ge Lexicográficamente menor, mayor,
menor e igual, mayor e igual
eq, ne Igual, distinto
cmp
Comparación de cadenas; devuelve -1, 0 o
1
x
Multiplicación de cadenas "az" x 2 eq
"azaz"
En esta misma línea se usa el operador !, de negación. Este operador, como otros muchos, están sacados directamente del lenguaje C, en general, los operadores en Perl
son los mismos que en C, y además tienen la misma prioridad. Además, hay una serie de operadores específicos para cadenas alfanuméricas, sacados más bien del
FORTRAN, y otros para ficheros que se verán más adelante.
En la línea 10 se escribe en el fichero MANTA; como se ve, simplemente se incluye el filehandle delante de la expresión que se va a escribir. Para terminar, después de
concluir el bucle se cierra el fichero.
Estos primeros programas nos permiten ya tener una idea de cómo funciona Perl. En realidad, salvo algunos asuntos menores de sintaxis de variables y su declaración, es
muy similar al C: por eso siempre, la primera aproximación a un programa será hacerlo tal como uno lo haría en C, para luego, cuando se tenga mayor dominio del
lenguaje Perl, hacerlo de forma más perlera.
El político corrupto se da cuenta de que tiene en un fichero guardadas una serie de sobornos anteriores en un fichero; pero no le puso nombre; así que, antes de que se le
vayan las cosas de la memoria y no diga nada salvo en presencia de su abogado, decide hacer un programa que le vaya preguntando cantidad por cantidad quién fue la
que se la dió. Y decide hacer el siguiente programa (recuerda.pl):
Listado : Programa recuerda.pl
1 #!/usr/bin/perl
2
3 open FICHERO, "cantidades";
4 open SALIDA, ">salida";
5 while($linea = ) {
6 chop($linea);
7 print "Quien te ha dado $linea pelas? Eh?\n";
8 chop( $menda = );
9 print SALIDA "$menda $linea\n";
10 }
11 close FICHERO;
12 close SALIDA;
Este programa utiliza las mismas estructuras que el anterior: ficheros de entrada y salida, y un bucle. Sin embargo, se usan de forma diferente. Para empezar, la sintaxis de
apertura de los ficheros en las líneas 3 y 4 es diferente: se evitan los paréntesis, casi 4 bytes, que en una memoria de 512 megabytes, quieras que no, es un ahorro. El
fichero cantidades se abre para lectura, por lo que no es necesario poner el símbolo <, y el fichero salida se abre para escritura.
Lo que sigue es bastante típico de la lectura de ficheros en Perl: se lee una línea del fichero abierto (usando la construcción <>, se asigna a la variable $line. Además, la
línea está dentro de una condición de continuación de un bucle; efectivamente, $line será la cadena vacía, y por lo tanto falso, cuando el fichero deje de tener
elementos.
El interior del bucle no aporta nada nuevo: simplemente se le eliminan los retornos de carro a lo que se lee usando chop, y se combina la entrada con lo que introduce el
usuario para escribirlo en la salida. Finalmente, en las líneas 11 y 12, se cierran los ficheros.
Ejercicios
Realizar un programa que vaya calculando cuadrados de números hasta que se introduzca una línea en blanco (solo retorno de carro).
Realizar un programa que permita al usuario introducir un nombre, y el ordenador le escriba "Hola >mismo nombre en mayúsculas<".
Realizar un programa que solicite nombres y apellidos del usuario, y los imprima en pantalla en formato formal: apellidos y nombre, separados por coma.
Escribir en un fichero todos aquellos que se llamen Juan de nombre.
Ahorrando energías
Operadores, matrices y la variable por defecto $_
Tutorial de Perl: Índice file:///home/jmerelo/txt/tutoperl2000/tutorial-print.html
6 of 20 13/02/03 12:48
Como nuestro político corrupto, por su experiencia en el ramo de la construcción, ha sido nombrado delegado de Obras Públicas, tiene que pasar la mayor parte del
tiempo visitando carreteras, caminos, puentes y veredas. Nada mejor, pues, que comprar un portátil AMD K6-2 para ir introduciendo las mordidas en el propio lugar
donde se originen. El problema es el limitado rango de las baterías, que hacen que si hay que viajar de Albacete a Cuenca, se gaste la batería a la altura de Motilla del
Palancar. Para ahorrar energía, decide modificar su programa de forma que escriba menos en el disco; es decir, que cargue todos los datos en memoria, y los guarde sólo
cuando termine el bucle. Además, para no poner la excusa a la comisión del Congreso (que ya pide Anguita a voces) de que no se acuerda de nada, decide grabar
también las fechas y horas de los sucesos. Escribe, con su pericia creciente en Perl, el programa memoria.pl (listado 3).
Listado : Programa memoria.pl
1 until(0) {
2 print "Cliente\n";
3 chop( $paganini = );
4 last if !$paganini;
5 print "Valor inmueble\n";
6 chop($valor = );
7 $comision = $valor * 0.25;
8 ($seg, $min, $hora, $dia, $mes, $anho, @zape) = localtime(time);
9 $mes++;
10 $anho+=1900;
11 $zipi = "$paganini $comision $hora:$min $dia/$mes/$anho\n";
12 push( @mem, $zipi );
13 };
14
15 open (MANTA,">clientes.mas");
16 foreach (sort @mem ) {
17 print MANTA;
18 }
19 close (MANTA);
En esta pequeña modificación del programa anterior, y en la línea 8, se introduce una nueva estructura de Perl: el array o lista. Un array se indica con el símbolo @
(arroba), aunque a cada elemento de un array nos referiremos con la notación $mem[0], ya que es un escalar. En general, tanto los operadores como las funciones en Perl
se comportan de forma diferente si se trata de un entorno escalar o si se trata de un entorno de lista o vectorial. En este caso, el operador localtime devuelve una lista
compuesta por los segundos, minutos y demas, tomándolo de la función time que devuelve el número de segundos transcurridos desde hace mucho tiempo (1970, para
ser exactos). Además, estamos utilizando la lista @zape para contener el resto de los elementos de la hora, que no nos interesan (serían el día de la semana y cosas así).
Por supuesto, también se podría haber hecho de otra forma, mucho más larga
@fecha= localtime(time);
$seg = $fecha[0];
...
Las matrices empiezan en Perl en 0 habitualmente, como sucede en C; pero esto se puede cambiar (usando la variable global $[). Hay que tener cuidadito con la variable
$anho, que devuelve, al contrario de lo que se pudiera pensar, el número de años transcurridos desde 1900. Eso da lugar a todo tipo de pequeños efectos 2000, que todavía
se ven por algún sitio Web. Por eso, en la línea 10, se le suma 1900, para que dé el año actual con cuatro cifras. Tal como en el lenguaje C, $anho+=1900 equivale a
$anho=$anho+1900;
En la línea 12 hay un nuevo operador, push. Este operador hace precisamente eso, achuchar un escalar o una lista al principio de otra lista (recordad que lista y array son
prácticamente sinónimos). En este caso, estamos metiendo la cadena que hemos creado, $zipi, al principio de la matriz @mem (que, por cierto, tampoco hemos tenido que
declarar ni dimensionar). Si queremos eliminar el primer componente de una matriz, se hace con el operador obvio, $cadena = pop(@mem);
En la línea 16 aparece una nueva orden de control de bucle: foreach, para cada, que repite el cuerpo del bucle para cada uno de los elementos de la lista que hay
contenida entre paréntesis. Se puede abreviar por for, aunque también se puede comportar como lo hace en C. ¿Y cuál es la lista a la que se aplica? La que hemos
creado anteriormente, pero por orden (de ahí el sort). En este caso la ordenará por orden alfabético, saliendo algo como esto
Uno 750 12:0 31/1/2000
otro 1402654 12:0 31/1/2000
otro mas 4020267 12:1 31/1/2000
y otro mas todavia 4040.25 12:1 31/1/2000
Sin embargo, dentro del bucle no parece que pase nada; y, ¿dónde diablos se ha metido la variable de bucle?. Lo que ocurre es que en estos casos Perl tiene una variable
por defecto, $_, que es la variable de bucle por defecto y sobre la que actúan los operadores y funciones también por defecto. Es decir, que el bucle anterior equivaldría a
foreach $_ (sort @mem) {
print MANTA $_;
}
Y aunque sé que ya estáis esperando que lo diga, se puede hacer de otra forma, esta vez menos Perlística; utilizando bucles normales y corrientes
for ($i = 0; $i<=$#mem; $i++) {
print MANTA $mem[$i];
}
si bien en este caso el fichero de salida no estará ordenado. En este caso se utiliza la construcción $#, que devuelve el último índice existente para esa
matriz. Ojo, se trata del último índice, no del número de elementos de la matriz; por eso los bucles en Perl usan un <= para terminar.
Ejercicios
Hacer un programa que imprima su entrada estándar en orden inverso,empezando por la última línea y acabando por la primera. Se ejecutará con
unix% cat ¦invert.pl
PistasUsar la orden pop, que extrae el primer elemento de un array. Reto Hacerlo en una sola línea.
$. es una variable que contiene la línea del fichero de la que se está leyendo. Teniendo esto en cuenta, crear un filtro (es decir, un programa que lea de entrada
estándar y escriba en salida estándar, tal como el anterior) que imprima un fichero con el número de línea al principio de cada una.
Hacer un histo(pro)gra, es decir, un programa que recoja una serie de valores numéricos (con valores reales entre 0 y 100), los distribuya en cinco cubos (del 0
al 20, entre 20 y 40, y así sucesivamente), calcule las frecuencias de cada uno de los cubos, e imprima barras horizontales cuya longitud es función de la
frecuencia.
Recordando, que es gerundio
Tutorial de Perl: Índice file:///home/jmerelo/txt/tutoperl2000/tutorial-print.html
7 of 20 13/02/03 12:48
La orden split, matrices asociativas y matrices bidimensionales
Al final del día, nuestro político corrupto reflexiona. ¿De qué sirve tanto trabajo, sin una buena contabilidad consolidada? (Además, tiene que presentarle las cuentas al
señor X a fin de mes). Idea, pues, el programa que aparece en el listado 4.
Listado : Programa totales.pl
1 die "Y el fichero de clientes, ein?\n" unless $ARGV[0];
2 while(<>) {
3 @linea = split;
4 @fecha=split(/\//,$linea[$#linea]);
5 $mesdia = "$fecha[1]-$fecha[0]";
6 $pasta=$linea[$#linea - 2];
7 $totalDia{$mesdia}+=$pasta;
8 }
91
0 foreach (sort keys %totalDia) {
11 print "Trinque total del dia $_ = $totalDia{$_}\n";
12 }
Este programa, aplicado sobre el ficheroclientes.mas, (resultado de una incursión en la construcción de diversas viviendas para los cuerpos de seguridad del estado y sus
departamentos de investigación y desarrollo, así como otros procedentes del mundo de la enseñanza) da el siguiente resultado (o algo parecido)
C:\PROGS\PERL>perl totales.pl clientes.mas
Trinque total del dia 3-24 = 598454.75
Trinque total del dia 4-25 = 1100987
Trinque total del dia 4-26 = 487775
Este programa empieza con una advertencia: "muere si no me metes un fichero como argumento". La orden die termina el programa con un mensaje; mientras que el
condicional que lo sigue comprueba que exista al menos un argumento para el programa; la matriz @ARGV contiene los argumentos pasados al programa; de forma que
$#ARGV dará el índice del último argumento, o sea que si es -1, indicará que no se ha pasado ningún argumento. Y otra forma de hacerlo sería
die "Sin argumento me lamento\n" if $#ARGV < 0;
O incluso
$ARGV[0] || die "Te has quedado sin argumentos\n";
que mira lo que hay a la izquierda del || (que es el "o" lógico), y si es cierto, ejecuta lo que hay a la derecha. Recuerda, en PERL hay más bla, bla.
El siguiente bucle, que comienza en la línea 2, tiene una extraña condición para que el bucle siga; sólo los dos ángulos enfrentados. Teóricamente, debería de haber un
filehandle dentro de esos ángulos (como se ha visto en un ejemplo anterior), pero en este caso, se está tomando el fichero por defecto, que es el fichero que se introduce
como argumento; en caso de que no se hubiera introducido ninguno tomaría entrada estándar, es decir, que habría que introducirle cada línea mediante teclado. A la vez,
y como se ha visto, esa orden toma una línea del fichero y la deposita en la variable por defecto, aunque, ojo, no le quita el retorno de carro final. Hay que tener en cuenta
que los paréntesis angulares sin argumento extraen elementos del array @ARGV usando pop, y abren un fichero con ese nombre; o sea que si hubiera varios nombres de
fichero en la línea de comandos, los iría abriendo uno por uno y disminuyendo consecuentemente el tamaño de @ARGV; conclusión, que si necesitas @ARGV para algo, mejor
que lo guardes antes de meterte en un bucle de esta guisa.
Sobre la variable por defecto actúa la orden split (una de las cosas más usadas en PERL), dividiéndola en una serie de cadenas separadas por espacios y depositando
cada una de esas cadenas en un elemento de la matriz @linea. Y dese cuenta el venerado público de con qué facilidad hemos hecho algo que requeriría al menos 10 líneas
de cualquier otro lenguaje. No hay que dimensionar matrices, no hay que recorrer la cadena caracter por caracter... ¡Nada!(3). Perdón, me he dejado llevar por el
entusiasmo.
La fecha es, en todos los casos, la última cadena de la línea; es decir, que será el último elemento de la matriz (cuyo subíndice es siempre $#vez tendremos que dividirlo, esta vez por la barra de separación, para luego poder poner el mes delante y que salga todo bellamente ordenado por meses en vez de por
días.
Esta cadena con la fecha, más la pasta, que está siempre 2 posiciones más a la izquierda (independientemente de la longitud de los nombres), se utiliza en la línea 7 en
una matriz asociativa . Esta es otra de las características más potentes del PERL, se pueden usar matrices cuyo índice es una cadena cualquiera, no sólo números enteros
positivos. Estas matrices asociativas encierran sus índices o claves entre llaves (¿os dáis cuenta del sutil mnemónico?). En esa línea, se le añade al componente de la
matriz indexado por la fecha la pasta de la entrada correspondiente. Así, hasta que se termina el fichero de entrada.
Para imprimir el informe, tres cuartos de lo mismo que en el programa anterior, salvo que en este caso, una matriz asociativa completa se indica con %, en vez de la arroba.
Ejercicios
Leer un fichero con el formato Primer_Apellido Segundo_Apellido, Nombre y escribirlo como
Nombre Primer_Apellido Segundo_Apellido
En el mismo fichero, presentar al final el número de veces que aparece cada apellido.
Realizar un programa que, haciendo lo mismo que el manta.pl, lo haga en la mitad de líneas.
Escribir un programa que haga lo mismo que la orden wc de UNIX, es decir, para cualquier fichero, contar el número de líneas, de palabras y de bytes, y
presentarlo en 3 columnas con el nombre del fichero en la cuarta. Hacer que funcione para varios ficheros, introducidos en la línea de comandos.
A partir del fichero de registro de visitas de un sitio Web, o log, poner cuántasveces han consultado las páginas desde dominios de primer y segundo orden,
presentarlos por orden, con una opción que permita seleccionar primer o segundo orden.
Realizar un programa que, a partir de una lista del tipo DNI Apellidos, Nombre genere un fichero de password, con el formato
username:password:uid:gid:Nombre y Apellidos
Calcular el username con la inicial del nombre y el primer apellido; si existe, usar el segundo apellido, y si existe también, añadir un número de orden. Para el
password, encriptar el DNI; el UID se genera por orden alfabético a partir del número 1000, el gid es un entero común, y el nombre y apellidos es elindicado. Al
terminarlo, ofrecerlo amablemente al administrador del sistema de tu Escuela o Facultad.
A partir de la versión 5 de perl , se pueden usar matrices bidimensionales, mediante un mecanismo que se llama referencias; este mecanismo no nos interesa ahora
mismo, pero sí como podemos usarlo en nuestros programas.