1- Introducción
1.1-PERL
1.1.1-¿Que es PERL?
1.1.2- Para que sirve
1.1.3- Donde puede usarse
1.1.4- Que fuentes de información existen
1.2- Filosofía de PERL
1.3- Diferencias entre PERL 4.3 y 5.X, Como
elegir Versión
2- Programación Básica
2.1- Estructura Básica de un programa,
programa Hola Mundo
2.2- Estructuras de datos básicas
2.2.1- Clases de Datos
2.2.1.1- Escalares
2.2.1.2- Arreglos
2.2.1.3- Hash o Arreglos asociativos
2.2.1.4- Equivalencias de Clases
2.2.3- Tipos especiales de Datos
2.2.3.1- Referencias
2.2.3.1.1- Creación
2.2.3.1.2- Uso
2.2.3.2- Archivos
2.2.3.2.1- Apertura
2.2.3.2.2- Uso y Cerrado
2.3- Operaciones Básicas
2.3.1- Aritméticas
2.3.2- Lógicas
2.3.4- Con Expresiones Regulares
2.3.5- Misceláneas
2.4- Estructuras de Control
2.4.1- Manejo de Subrutinas
2.5- Operaciones con Archivos
2.5.1- Apertura y Cerrado
2.5.2- Lectura de Datos
2.5.3- Escritura
2.5.4- Saltos y Proceso binario
2.6- Operaciones con Recursos del sistema
2.6.1- Como expresiones
2.6.2- Sin interrelaciones
2.6.3- Entubados
3- Programación Especial
3.1- Uso de Perl en línea, Tareas Comunes
3.1.1- Formas de Especificar el programa
3.1.2- Interruptores
3.1.3- Tareas Comunes de Perl en Línea de Comando
3.1.3.1- Reemplazar una cadena en un archivo por otra
3.1.3.2- Imprimir algún campo de un archivo
3.2- Programación de CGI, en Perl
3.2.1- cgi-lib.pl
3.2.2- CGI_Lite
3.3- Scripts para elaboración de reportes de texto
3.4- Expresiones Regulares
3.4.1- Símbolos Normales
3.4.1.1- Individuales
3.4.1.2- Genéricos
3.4.2- Símbolos Especiales
3.4.3- Uso de Expresiones regulares
3.4.3.1- Búsqueda
3.4.3.2- Substitución
3.4.4- Variables
3.4.4.1- Variables de entrada
3.4.4.2- Variables de salida
INTRODUCCION
1.1- PERL
1.1.1- Que es PERL
Perl (Practical Extraction and
Report Languaje) es un lenguaje deprogramación surgido a
inicios de los noventas, que busca antes que nada el
facilitar la elaboración de tareas comunes en sistemas tipo
UNIX, donde tradicionalmente las tareas de administración
y proceso de datos se realiza con herramientas muy rudimentarias
y por demás hostiles al usuario o administrador. Pero que
se aplican sobre grandes cantidades de información (por lo
regular texto) por lo que se requiere que sean de alto rendimiento.
Su autor, Larry Wall (lwall@netlabs.com) realizó Perl casi
como una obra altruista, de modo que hasta PERL 5.X su distribución
es gratuita, sin que por eso tenga menos poder o consistencia.
1.1.2- Para que sirve
Perl surgió como una opción
para una gran cantidad de herramientas de UNIX en las cuales basa
su propia sintaxis, buscando el mínimo sacrificio de su desempeño
por una máxima facilidad de programación e integración,
sigue la filosofía de mantener un ambiente que sea capaz
de detectar y corregir pequeñas omisiones del programador,
y de proporcionarle una forma abreviada de realizar múltiples
tareas. En una palabra, es una utilería que pretende facilitar
el proceso de grandes volúmenes de información sin
sacrificar el rendimiento.
1.1.3- Donde Puede Usarse
Las plataformas donde Perl se
ha desarrollado mas son los servidores UNIX, por sus necesidades
de administración y lo robusto de su manejo de memoria y
de procesos (requisitos de PERL hacia el S.O.) además de
la facilidad de Perl para realizar los así llamados CGIs,
interfaces para comunicar recursos del servidor con un servicio
de internet particular (como podría ser WWW o gopher), En
otras plataformas, PC en particular, se han desarrollado versiones
que mantienen un razonable grado de funcionalidad, pero en realidad,
el sistema DOS no tiene un manejo lo bastante bueno de los procesos
o de la memoria para permitir a PERL dar un buen desempeño,
además de que no es común ver en PC necesidades de
administración de la magnitud de un servidor institucional.
Sin embargo, puede practicarse la programación en PERL de
PC, o incluso elaborar programas de reporteo en el , sin embargo,
es algo que no se ha popularizado hasta hoy.
1.1.4- Que fuentes de información existen
Los libros que son ya clásicos
sobre Perl son los libros del camello y la llama de la editorial
Nutshell, además, existen magníficas introducciones
y manuales de referencia que se pueden obtener vía internet.
Aun cuando es imposible mencionar con precisión las fuentes
de información de un medio tan dinámico con algo tan
estático como este documento. Debe notarse, además
que estas referencias están en inglés.
Para buscar información, Yahoo! por supuesto:
Debo recalcar que por la
misma naturaleza de Perl, los recursos disponibles y las herramientas
que se pueden utilizar cambian muy a menudo, por lo que es indispensable
dedicar algún esfuerzo a mantenerse al día para evitar
un desperdicio mayor de esfuerzo por no utilizar los nuevos recursos
disponibles.
1.2- Filosofía de Perl
"Hay mas de una forma de
hacerlo"
-Larry Wall, autor del lenguaje de programación Perl.
Perl no establece ninguna filosofía de programación
(de hecho, no se puede decir que sea orientado a objetos, modular
o estructurado aun cuando soporta directamente todos estos paradigmas),
los objetivos que se tuvieron en cuenta al diseñar la sintaxis
de Perl fueron la facilidad de aprendizaje y de uso y la claridad
de código, las cuales, considero que son necesarias (aunque
pueden escribirse programas en Perl complejos e inteligibles si
así se desea).
Por si fuese poco, Perl no es ni un compilador ni un interprete,
esta en un punto intermedio, cuando mandamos a ejecutar un programa
en Perl, se compila el código fuente a un código intermedio
en memoria, se le optimiza (como si fuésemos a elaborar un
programa ejecutable) pero es ejecutado por un motor, como si se
tratase de un interprete. El resultado final, es que utilizamos
algo que se comporta como un interprete pero que tiene un rendimiento
comparativo al de programas compilados. Sin embargo, ya existen
compiladores de Perl con la versión 5.
En fin, Perl no nos forza a nada, pero como es lógico hay
ciertas reglas que recomiendo seguir para facilitar nuestro trabajo:
Claridad. En la mecánica de programación actual, los
programas deben de ser entendibles por la persona que nos suceda
en tareas de mantenimiento, de lo contrario perjudicamos tanto a
nuestros compañeros de trabajo como a nuestra propia libertad
para progresar y mantenernos libres de preocupaciones. Indentación.
Una costumbre ya clásica de la programación, en lo
personal, y a lo largo de los ejemplos de este documento, indento
el código dos espacios hacia adelante al abrir cada bloque,
y termino la indentación al terminar el bloque, de modo que
las llaves de apertura y cierre quedan a la vista y en la misma
columna, solas en sus renglones (esto incrementa algo el numero
de
líneas, pero facilita sobremanera la búsqueda y corrección
de los diversos bloques de control).
Nombres de variables y demás. En lo personal, procuro dar
la máxima claridad a los nombres de las variables sin hacerlos
demasiado grandes, el nombre de los contadores y variables que guardan
valores concernientes a un pequeño segmento de código
por lo regular son de un par de letras (c1, c2, ... cx para los
contadores, s1, s2, etc para cadenas de entrada etc.) mientras que
las variables que afectan a diversos segmentos (a modo de regla,
que tienen su definición en una pantalla distinta a donde
se usan) tienen nombres explicativos que procuro no excedan los
12 caracteres. Además, los nombres de archivos se usan con
mayúsculas (ARCHENT, ARCHSAL, etc) y las clases tienen su
primera letra mayúscula.
Comentarios. Para facilitar la comprensión de un programa
no hay como explicarlo, y los comentarios son el medio ideal para
hacerlo, hay por lo menos tres comentarios que considero que siempre
deben incluirse en un programa: Que hace el programa, Quien lo escribió
y Cuando inicio y termino de escribirlo, sobretodo en el contexto
de una organización, estos tres simples comentarios pueden
hacer la diferencia entre desechar un programa como indescifrable
o dedicarle algún tiempo para revisarlo. Además, considero
prudente comentar dentro del código la forma en que el programa
deberá ejecutarse, parámetros, y su sintaxis, así
como comentar las estructuras de control como un modo de explicar
la funcionalidad al detalle y recalcar con comentarios las funciones
que cumplen las variables.
Sencillez. Es cómodo en ocasiones el comprimir una serie
de instrucciones en una sola línea, queda al criterio decidir
cuando se gana en claridad con un código mas o menos extenso,
pero no debe titubearse en comentar el código que sea "comprimido".
1.3- Diferencias entre Perl 4.3 y 5.X, Como elegir versión
Actualmente existen dos versiones
altamente populares de Perl, la 4.3 y la 5.0X, de hecho hay diferencias
importantes entre una versión y otra. Seguramente el lector
se pregunta porque surge la duda entre usar una versión vieja
y una nueva, por regla general las nuevas versiones son mejores
que las anteriores de modo que las opacan en todo sentido, Perl
no es la excepción a esta regla, el único factor que
impide una transición inmediata es que no son 100% compatibles.
La versión 5 de Perl es una reescritura total que ya incluye
un manejo de estructuras abstractas de datos mucho mas poderoso,
incluso, soporta la orientación a objetos a su manera (tema
que no trato en esta introducción). De modo que las librerías,
por ejemplo para creación de CGIs no funcionan de una función
a otra por lo que la migración es poco practica.
Así pues, la decisión sobre que versión utilizar
depende del trabajo que haya sido realizado con anterioridad, si
ya se tiene un sistema completo o grande en Perl 4, es recomendable
mantenerlo en Perl 4 por el resto de su vida útil, pero para
desarrollos nuevos es por mucho, mas recomendable iniciarlos con
Perl 5 o en su caso, la versión mas reciente que este disponible,
por experiencia se que la capacitación para adaptarse a la
nueva versión es extraordinariamente corta dada la importancia
de las mejoras. Una tercera opción (que es por mucho la mas
recomendable si se tienen los recursos) consiste en instalar las
dos versiones de modo que convivan en el sistema.
2- Programación básica
En este capitulo daremos una
rápida revisión a los conceptos mas usuales que se
encuentran en un programa en Perl, trataremos de ver la implementación
para ambas versiones 4 y 5 cuando sea posible, especificando siempre
en que versión esta el ejemplo original (dando preferencia
a la versión 5) y al menos las alternativas para implementarlo
en la otra versión.
Los ejemplo requerirán para funcionar, que se tenga Perl
instalado en la maquina en que se practique y deberá conocerse
la ruta completa al binario de Perl.
Mas que sentirse en libertad de experimentar con los diversos ejemplos,
deben sentirse obligados a experimentar, modificar y explorar por
su cuenta cada que sea posible, tomando los ejemplo solo como un
punto seguro de partida. Para este fin, recomiendo que se tenga
acceso desde el inicio a alguna referencia del lenguaje (ya sea
el libro Programming Perl (del Camello) de la Nutshell o alguna
referencia disponible por WWW), este documento pretende explicar
lo básico de un modo accesible para que después pueda
el nuevo programador de Perl abordar sin temor los materiales mas
detallados.
2.1- Estructura Básica de un programa,
programa Holamundo.
Como se menciona en la introducción,
Perl no obliga a casi nada, así pues, lo que planteo como
estructura básica es mas bien una convención que un
requisito del lenguaje, a diferencia de Pascal (por ejemplo) Perl
no tiene una plantilla para sus programas y si se adoptan algunos
protocolos es solo por comodidad.
Los programas de Perl, por lo regular, inician con la línea:
#!/usr/bin/perl
Esta línea, indica al SO que lo que sigue es un script de
Perl, y que "Perl" (el programa con el cual debe ejecutarse)
esta en el directorio "/usr/bin", la secuencia "#!"
es una secuencia que UNIX reconoce, no Perl.
Un método alterno, que funciona para otras plataformas, es:
en lugar de colocar esa primera línea ejecutamos:
Perl nombre_del_script.pl de modo que directamente se ejecuta el
interprete de Perl pasándole como primer parámetro
el script a ejecutar (los demás parámetros se tomaran
como parámetros al programa). Si se requiere deberá
sustituirse "Perl" por la ruta completa del programa y
el nombre que el programa tenga.
Para los ejemplos sucesivos, tomare la suposición de que
se trabaja en un sistema UNIX con el interprete de Perl en el directorio
"/usr/bin".
Y eso es toda la estructura básica!.
Programa Hola mundo:
#!/usr/bin/perl
print "Hola Mundo\n"; #Saluda
#Programa Hola Mundo, Daniel Sol Llaven, 1996, como parte del tutorial
de Perl
Este programa, se escribe como un archivo de texto común,
(al que recomiendo se le ponga extensión ".pl")
y se cambian sus permisos para que pueda ser ejecutado (por lo regular
con un "chmod 700 nombre_programa.pl" en sistemas UNIX),
para ejecutarlo simplemente se invoca el nuevo script "nombre_programa.pl",
hay que recordar que para el sistema particular en que se este trabajando
es muy probable que deba modificarse "/usr/bin/" por otra
ruta.
Así, la ejecución en un sistema UNIX podría
verse como:
>chmod 700 Hola.pl
>Hola.pl
Hola Mundo
>Hola.pl
Hola Mundo
>
Ejecutando dos veces el script pretendo mostrar que no es necesario
cambiar el modo de ejecución del script sino solo una vez.
Expliquemos las tres líneas que constituyen nuestro primer
script:
#!/usr/bin/perl
Esta línea, propiamente dicho, no es parte del script de
Perl, sino una instrucción al SO para indicar que las siguientes
líneas deberán interpretarse por el programa "/usr/bin/Perl",
si se omite, o no funciona en el sistema operativo, podemos ejecutar
el programa de la siguiente forma:
>/usr/bin/Perl Hola.pl
Hola Mundo
>print "Hola Mundo\n"; #Saluda
Esta es la única instrucción del programa y esta acompañada
por un comentario, la instrucción es:
print "Hola Mundo\n";
que pudo ser escrita como:
print("Hola Mundo\n");
sin que esto implicara el mínimo cambio en funcionalidad.
a continuación tiene el comentario:
#Saluda
La sintaxis de C para comentarios no funciona en Perl, pues se usa
a "/" para expresiones regulares.
#Programa Hola Mundo, Daniel Sol Llaven, 1996, como parte del tutorial
de Perl
Esta línea es otro comentario, el SO y Perl consideran todo
lo que este en una línea que inicie con "#" como
comentario. (excepto en el caso de que sea una primera línea,
el SO lo interpreta como la indicación del interprete, pero
Perl lo ignora como a cualquier otro comentario).
2.2- Estructuras de Datos Básicas
En nuestro programa Hola.pl no
utilizamos ninguna variable, por lo que para explicar estos conceptos
necesitaremos un nuevo programa, HolaP.pl que es una versión
personalizada de Hola.pl.
#!/usr/bin/perl
#Programa Hola Mundo personalizado, Daniel Sol Llaven 1996, Tutorial
Perl.
print "Hola ?como te llamas?:";
$nombre=<STDIN>;
chop($nombre);
print "$nombre!, bonito nombre, cuantos años tienes?:";
$edad=<STDIN>;
print "sabias que te faltan ".(100-$edad)." para
tener 100?\nAdios!\n";
Su ejecución genera resultados similares a los siguientes:
>HolaP.pl
Hola ?como te llamas?:Daniel
Daniel!, bonito nombre, cuantos años tienes?:22
sabias que te faltan 78 para tener 100?
Adiós!
>
En este programa, aparecen muchos elementos novedosos que iremos
revisando poco a poco a lo largo de este documento, por el momento,
revisemos que hace línea por línea:
#!/usr/bin/perl
#Programa Hola Mundo personalizado, Daniel Sol Llaven 1996, Tutorial
Perl.
Cabecera normal del programa, incluido comentario indispensable.
print "Hola ?como te llamas?:";
Esta línea escribe "Hola ?como te llamas?:" pero
nótese que no escribe una vuelta de carro al final (omite
el "\n").
$nombre=<STDIN>;
Aquí asignamos a $nombre un renglón escrito por la
entrada estándar del programa.
Perl define al "archivo" STDIN como su entrada estándar,
y el operador <> que indica la lectura de una línea
de un archivo de texto, de modo que <STDIN> indica la lectura
de un renglón de la entrada estándar (al menos para
el ejemplo!), este tema se tratara con cuidado en la sección
2.5 y 3.3 de este documento que tratan de operaciones con archivos.
Para fines prácticos, usaremos <STDIN> como la expresión
que lee una línea de entrada del usuario desde teclado.
chop($nombre);
Perl, al leer la línea escrita por el usuario, también
toma el enter que el usuario da, de modo que en el ejemplo, la entrada
que di en vez de ser "Daniel" se puede escribir como "Daniel\n",
(siendo "\n" el carácter de vuelta de carro), la
función "chop()" tiene la función de eliminar
el ultimo carácter a nuestra cadena, de modo que después
de esta instrucción $nombre solo tiene "Daniel".
Por las características de la lectura de renglones de archivos,
chop() es un elemento casi constante en programas de Perl.
(Pruébalo!, revisa que sucede si comentas esta línea,
veras que al imprimir el nombre imprime también el retorno
de carro avanzando una línea hacia abajo).
print "$nombre!, bonito nombre, cuantos años tienes?:";
Esta línea nos muestra como se imprime el contenido de nuestras
variables de forma sencilla; notamos que en la cadena a imprimir
se encuentra $nombre, el compilador lo interpreta y reemplaza por
su valor, (para imprimir "$" se pone "\$"),
el resto de la cadena es completamente convencional.
$edad=<STDIN>;
Esta línea, lee otra línea de TEXTO y la coloca en
la variable $edad (con todo y retorno de carro).
print "sabias que te faltan ".(100-$edad)." para
tener 100?\nAdios!\n";
Esta línea imprime un mensaje que esta dividido en tres partes,
la primera y la ultima son cadenas convencionales, que están
concatenadas (operador .) con una operación aritmética.
Hay que notar que edad era un renglón de la entrada estándar,
y no un numero, sin embargo no hay conflicto de tipo al operarlo
con un entero, ¿porque? porque los dos, para Perl, son del
mismo tipo, son escalares, después discutiremos que son los
escalares y que mecanismo de conversión se utiliza para extraer
el entero del texto contenido en $edad.
(Experimenta!, prueba que pasa si los valores que se dan a edad
no son enteros, que pasa si son reales o cadenas!)
Después de nuestro primer encuentro con las variables de
Perl, el sentimiento mas probable es el de perplejidad, ¿como
maneja sus variables?,
¿a que me refería conque enteros, reales y cadenas son
del mismo tipo?, y si es así, ¿como serán los
demás tipos?.
En realidad, las variables de Perl pretenden simplificarnos la vida,
pero debemos comprender como pretenden facilitar las cosas para
no terminar peleando contra ellas.
2.2.1- Clases de Datos
Perl reconoce tres clasificaciones
básicas de datos, y dos especiales, por claridad, llamaremos
clases a estas diversas clasificaciones, y tipos a las formas usuales
de datos.
Las diversas clases se distinguen entre si por el símbolo
que antecede al nombre de la variable (por ejemplo $nombre es una
variable de tipo escalar que se llama "nombre"), debe
notarse que no hay relación entre variables del mismo nombre
si son de clases distintas.
A continuación, pongo una tabla de las clases de datos y
los tipos que contienen:
Clase Símbolo Tipos
Escalar $ Entero, Real, Cadena, Referencia*
Arreglo @ Arreglo de escalares
Hash % Arreglo Asociativo de escalares
Archivo (ninguno) Identificador de Archivo
Type Glob * Cualquiera**
* Las referencias son exclusivas de Perl 5, son el equivalente a
apuntadores.
** Las variables tipo Glob se usaban como sustituto de las referencias
en Perl 4, son obsoletas para Perl 5 y en lo personal no recomiendo
su uso sino en casos muy particulares.
2.2.1.1- Escalares
Nota: Algunas características
de las conversiones entre tipos son exclusivas de Perl 5, pero la
sintaxis y características generales son las mismas para
ambas versiones. Por lo que en general, el tratamiento expuesto
es valido para las dos.
El escalar, es la clase de datos que engloba los tipos convencionales
de datos, de modo que podemos decir:
$v1="Daniel Sol Llaven";
$v1=100;
$v1=89.12;
Sin que esto implique ningún cambio en la naturaleza de $v1,
en todo momento es un escalar.
Aun cuando la compatibilidad de datos enteros y reales es fácil
de imaginar, la conversión implícita en el caso de
las cadenas no lo es, sin embargo la regla es bastante simple.
por ejemplo:
$v1="123y321";
crea un escalar $v1, que contiene la cadena "123y312",
¿pero que pasa si le deseamos sumar 4?. Perl, interpreta $v1
como entero (o punto flotante) para esto, toma todos los caracteres
del inicio que forman un numero correcto y ese numero es el que
interpreta; de modo que:
print $v1+1;
imprimirá:
124
Del mismo modo, como ejemplo:
$v2="123.123.123"+1
da el valor 124.123 a la variable $v1 (punto flotante).
Otro punto importante de las variables en general es que, aunque
en ningún momento se declaran como de un tipo o de otro,
si se pueden "destruir", o revisar que hayan recibido
algún valor en la ejecución del programa, esto se
logra mediante las funciones defined() y undef(). defined nos indica
si la variable que le pasamos como argumento ha sido definida (es
decir, existe en el programa) o no. undef toma una variable y la
"elimina" de modo que ya no tiene valor y defined la reporta
como no utilizada.
Los valores lógicos de verdadero y falso se manejan de modo
similar al de C, cualquier valor escalar no nulo o cero se considera
verdadero. Debe tenerse cuidado con las cadenas "0" pues
si se evalúan como número resultaran en falso aun
cuando no son cadenas nulas.
Los escalares son los constituyentes de las demás estructuras
de datos, por lo que al explicar los arreglos, hashes, referencias
y archivos haremos muchas referencias a ellos.
2.2.1.2- Arreglos
Los arreglos en Perl
son simplemente, arreglos dinámicos de escalares, es decir,
se pueden usar cualesquiera elementos en el arreglo y Perl se encargará
de hacer al arreglo de la dimensión adecuada.
La definición de un arreglo con valores constantes es:
@a1=("hola",123,43.2,"adios");
Esta definición, crea el arreglo @a1 con cuatro elementos,
dos cadenas, un entero y un real, en realidad, cuatro escalares,
para hacer referencia a los elementos escalares de un arreglo se
usan los corchetes [] indicando el índice del elemento (de
cero al numero de elementos menos uno) de modo que:
print "$a1[0]\n$a1[1]\n$a1[2]\n$a3[3]\n";
resulta para el arreglo anterior:
hola
123
43.2
adiós
Nótese que el elemento de un arreglo ya no es un arreglo,
sino un escalar, y debe especificarse como tal, con $ en vez de
@. No es lo mismo el escalar a1 que un elemento del arreglo a1.
$a1 Es un elemento distinto que $a1[]
Por claridad, recomiendo que no se dupliquen nombres de arreglos
(o cualquier otra cosa) con escalares, aunque Perl da un manejo
independiente a las diversas entidades, de modo que si se hace no
habrá quejas de parte de Perl.
Es importante señalar que los arreglos y hashes no pueden
ser elementos de un arreglo, si se intenta esto, los arreglos o
hashes serán "aplanados" a elementos que se agregan
al arreglo. Por ejemplo:
(a,b,(c,d),e)==(a,b,c,d,e)
Es decir, el arreglo constante a,b, arregló con c,d , e es
equivalente al arreglo que contiene a,b,c,d,e. Pues al formar el
primer arreglo, el sub-arreglo c,d es "aplanado" a elementos
que se agregan al arreglo principal. Algo similar sucede a los hashes.
Para hacer arreglos de arreglos o arreglos como elementos de hashes,
se utilizan las referencias.
2.2.1.3- Hash o Arreglos Asociativos
El Hash, o arreglo asociativo
es una ampliación del arreglo, en la que en vez de ubicar
los elementos por posición se les ubica por una "llave"
es pues un arreglo de parejas ordenadas que se accesa por el primer
elemento, el símbolo de los hashes es %, y la forma de declarar
un hash con constantes es muy similar a la forma para declarar un
arreglo:
%h1=("ll1",1,"ll2",2,"ll3",3);
Esta declaración crea un hash con tres parejas ordenadas,
las llaves son "ll1", "ll2", "ll3",
para usarlo se pueden usar expresiones del tipo:
$ndx="ll3";
print "$h1{ll1}\n$h1{"ll2"}\n$h1{$ndx}\n";
resultando:
1
2
3
Al igual que en los arreglos, cada elemento de un hash es un escalar,
de modo que debe anteponerse $ en vez de % (pues no estamos haciendo
referencia a todo el hash, sino a un elemento escalar del hash),
pero a diferencia del los arreglos, en vez de usar [] para indicar
el índice se usan las llaves {}.
Dentro de las llaves, en el ejemplo, usamos las tres formas principales
de dar el índice: ll1 - En esta forma Perl adivina correctamente
que ll1 es una cadena y que esta es la llave.
"ll2" - En esta forma decimos explícitamente el
valor de la llave deseada.
$ndx- como $ndx="ll3" Perl puede determinar el valor de
la llave correcta.
Para índices, al igual que para hashes, también puede
usarse el valor de variables o de expresiones para especificar el
índice.
2.2.1.4- Equivalencias de Clases
Como ya revisamos, al
hacer referencia a un elemento particular de un arreglo o hash obtenemos
un escalar (en ves de todo el arreglo o hash). Este tipo de "cambios"
de clase son el propósito de esta sección, pues pueden
resultar algo confusos aunque, una vez comprendidos, dan una buena
parte del sabor peculiar de Perl.
Básicamente, Perl distingue dos tipos de contextos para evaluar
una expresión: como escalar y como arreglo. El primero se
refiere a las expresiones que han de regresar un escalar (del tipo
que sea) como resultado, y el segundo a aquellas expresiones que
han de regresar un arreglo o conjunto de escalares como resultado.
Muchas expresiones pueden ser evaluadas en ambos contextos y obtener,
según el contexto, un resultado distinto, esto lo revisaremos
con cuidado conforme vayamos revisando estas expresiones.
Revisemos los cambios que ocurren a los datos de una cierta clase
cuando los evaluamos en otro contexto:
-------------------------------------------------------------------
Contexto escalar arreglo
Clase escalar arreglo hash
escalar escalar El valor Se convierte en Vacío, no definido
original el único elemento del arreglo arreglo arreglo Numero
de El arreglo de Los elementos pares elementos valores (0,2,4,...)
forman (usualmente) originales las llaves y los nones los datos
del nuevo hash.
hash cociente que arreglo con las El hash original representa la
parejas eficiencia del llave1,valor1,lla hash ve2,valor2,...
-------------------------------------------------------------------
Las transiciones mas utilizadas
son las de arreglo a escalar, las de arreglo a hash y de hash a
arreglo, la primera porque permite conocer el tamaño de los
arreglos y las segundas porque proveen los mecanismos para inicializar
los hashes con arreglos constantes y para "aplanarlos"
con fines de almacenamiento e impresión.
A menudo, se representa un arreglo con una sola cadena que contiene
separadores para los diversos elementos, Perl implementa la función
"split" que divide estas cadenas en arreglos, su sintaxis
básica es:
split($delim,$cadena)
donde $delim es la expresión que representa los delimitadores
de elementos y $cadena es la cadena a dividir.
Como ya se mencionó, generará un arreglo de cadenas
donde los elementos son las subcadenas de $cadena que estén
separadas por cadenas $delim.
por ejemplo, una cadena como:
$registro="Daniel:22:daniel\@simba";
@reg=split(":",$registro);
print "Nombre:$reg[0]\nEdad:$reg[1]\nEmail:$reg[2]\n";
genera un resultado similar a:
Nombre:Daniel
Edad:22
Email:daniel@simba
Cuidado! no todas las funciones de Perl convierten de igual forma
los arreglos en escalares, por lo que debe provarse o investigar
primero que efectivamente en el contexto en que hagamos la conversión
el resultado sea el deseado.
Ejemplos:
Arreglo constante
@arreglo=(1,2,"hola",3,"adios");
inicializa el arreglo @arreglo con los elementos 1,2,"hola",3,"adios",
(todos escalares). la notación de los elementos entre paréntesis
define un arreglo constante, el equivalente a un numero o cadena
constante cuyo valor asignáramos a una variable pero en el
contexto de los arreglos.
"Hash" constante
%hash=("llave1","dato1","llave2","dato2);
#arreglo constante a hash Inicializa el %hash con las llaves "llave1"
y "llave2" poniéndole como contenidos "dato1"
y "dato2" respectivamente. De hecho, no especificamos
un "hash constante" como en el caso del arreglo, sino
que especificamos un arreglo constante el cual pasa por una transformación
de clase para asignarse a un hash, de modo que la expresión
es equivalente a:
@arreglo=("llave1","dato1","llave2","dato2);
#arreglo constante a arreglo
%hash=@arreglo; #arreglo a hash
Cardinalidad de un arreglo
@arreglo=(1,2,3,4);
$elementos=@arreglo;
En este caso $elemento recibe el valor 4, pues son 4 los elementos
del arreglo, nótese que el índice máximo en
el arreglo es de solo tres, pues el primer elemento es el elemento
0 y Perl 4 regresa, con esta misma expresión el índice
máximo en lugar del número de elementos como Perl
5.
Asignación a arreglo constante
($a,$b,$c)=(1,2,3);
Esta expresión es equivalente a:
$a=1;
$b=2;
$c=3;
Pero debe tenerse cuidado, el siguiente código:
($a,$b,$c)=(1,2,3);
@a=($a,$b,$c);
$a=7;
$b=8;
$c=9;
Da al arreglo @a el valor del arreglo constante (1,2,3), y no, como
podría pensarse. (7,8,9). Cuando se genera un arreglo constante
se evalúan los elementos que lo forman como constantes escalares
y se le asigna después, para obtener resultados diferentes
se deberá usar un arreglo de referencias.
Arreglos con arreglos
@a=(1,2,3);
@b=(5,6,7);
@c=(@a,4,@b,8);
Estas expresiones generan tres arreglos, (1,2,3), (5,6,7) y (1,2,3,4,5,6,7,8),
y no, como podría pensarse un arreglo de arreglos, cuando
incluimos un arreglo dentro de otro, Perl "aplana" el
arreglo insertado como si insertara uno a uno todos sus elementos
en la posición indicada del arreglo que ha de contenerlos,
para hacer arreglos de arreglos deberemos usar referencias a estos.
2.2.3- Tipos Especiales de Datos
Llamo a estos "tipos
especiales" porque nos permiten hacer cosas inposibles con
otros tipos, por ejemplo, el evitar ser "aplanado" en
los arreglos. Además, incluyo en esta sección a los
Archivos, pues aunque su sintaxis se parece a las de las variables,
su funcionalidad es bien distinta. Sin embargo, por tratarse de
solo una introducción omito discutir sobre los "type
globs" que son la aproximación a las referencias que
perl 4 implementa.
2.2.3.1- Referencias
Nota: Este tipo de datos
es exclusivo de Perl 5, Perl 4 usaba los type globs para realizar
algunas de estas funciones, pero el proceso es mucho mas complicado
y obscuro.
Las referencias son el equivalente lógico de los apuntadores,
son un tipo de dato que no contiene información en si misma,
sino que permite manejar indirectamente los datos contenidos en
otra entidad.
Las referencias, sin embargo, no forman una clase nueva de datos,
sino que son tratados como un tipo mas de escalar.
La definición de referencias se realiza por el operador referencia
"\" (backslash) , funciona de modo similar a "&"
en C, y aunque a diferencia de C no hay un operador de derreferencia
la sintaxis para acceder al dato original es muy sencilla.
A diferencia de C, los objetos que creemos mediante referencias
no quedan como cadáveres en memoria, Perl lleva un registro
de las diversas
referencias a cada elemento en memoria y automáticamente
lo destruye cuando descubre que nadie hace ya referencia a él,
de modo que pueden usarse las referencias sin miedo, aunque con
la precaución necesaria para no perder los datos que almacenamos
en ellas.
2.2.3.1.1- Creación
Podemos crear referencias
de varias formas, las que considero mas sencillas y útiles
son:
Usando el operador de referenciación en una variable, o valor,
en el caso de una variable, es crear un medio alterno de acceder
al valor de la variable.
$rescalar=\$escalar;
$rarreglo=\@arreglo;
$rhash=\%hash;
$rrutina=\&subrutina; #la programación de subrutinas
la revisaremos mas adelante.
$globref=\*ARCHIVO; #solo revisaremos los type globs para usarlos
como referencias a archivos.
Creando objetos "anónimos" que solo pueden ser
accesados por medio de la referencia.
Escalares
$rescalar=\"hola"; #referencia a la cadena anónima
"hola"
Arreglos:
$rarreglo=[1,2,3]; # referencia al arreglo anónimo (1,2,3)
Hashes
$rhash={"llave1"=> "dato1","llave2"=>
"dato2"};
Nótese que en esta representación usamos además
el operador "=>" que indica una pareja de llave y dato,
las que se separan por comas; esta notación también
es valida para hashes convencionales, pero la claridad que agrega
es mejor utilizada al declarar hashes anónimos.
Como elementos de arreglos y/o hashes para formar estructuras de
datos complejas, al ser escalares, son elementos del arreglo sin
mas complicación,de modo que los arreglos a los que hacen
referencia se mantienen intáctos.
Por ejemplo, para formar un hash que contenga arreglos de nombres
de letras:
%rhletras={
"latinas"=> ["a","b","c"],
"gregas"=> ["alfa","beta","gamma"]};
Esta sentencia forma un hash donde las llaves son cadenas y los
datos son referencia a arreglos.
Pueden convinarse las referencias a arreglos y a hashes anónimos
a voluntad para formar una estructura de datos tan compleja como
se desee.
2.2.3.1.2- Uso
De nada sirven las referencias
si no podemos extraer y modificar los datos contenidos en los elementos
señalados por la referencia, en Perl la forma para obtener
el valor y para modificarlo es casi la misma, solo las abreviaturas
de las referencias para obtener el valor funcionaran de modo distinto
cuando tratemos de asignarles valor.
Aun cuando Perl tiene varias formas de "derreferenciar"
la información, solo discutiré dos por considerarlas
las mas sencillas, sin embargo, recomiendo una revisión al
capitulo PERLREF de la referencia de Perl 5.X para una explicación
mas detallada y a consciencia del manejo de las referencias.
Uso "simbólico" de las referencias.
Por regla general, podemos usar las referencias como si se sustituyeran
antes de ejecutar el código (aunque en realidad, no sea así),
de modo que el código:
$nombre="entero";
$entero=5;
$rentero=\$entero;
$$nombre=6;
$$rentero=7;
efectivamente cambia el valor de $entero de 5 a 6 y despues de 6
a 7, del mismo modo podemos usar las referencias refiriéndonos
a cualquier otro tipo.
por ejemplo, para arreglos:
$rarreglo=[1,2,3,4] #crea arreglo anónimo (1,2,3,4)
$$rarreglo[2]="tres"; #modifica el arreglo anónimo
a (1,2,"tres",4)
@$rarreglo=(); #limpia el arreglo anónimo
Uso con el operador de derreferencia.
Como una forma de abreviar el proceso para referencias a arreglos
y hashes, se añadió el operador -> que indica que
el escalar es una referencia a hash o arreglo y espera el índice
después.
por ejemplo:
$rarreglo->[5]="algo";
coloca "algo" como el 6o elemento del arreglo al que hace
referencia
$rarreglo.
$rhash->{"alfa"}="uno";
coloca la pareja ("alfa"=> "uno") en el hash
al que hace referencia $rhash.
Uso abreviado del operador de derreferencia.
Se pueden obtener referencias a referencias, y se pueden hacer arreglos
de referencias, de modo que los arreglos multidimencionales se pueden
elaborar con la misma mecánica que en C.
$ra3d->[0]->[0]->[0]=1; #pone un "0" en la primera
celda de un arreglo tridimencional
Nótese que al crear perl los arreglos de las dimensiones
adecuadas automáticamente no hay problemas de invasión
de memoria no reservada (aunque un uso descuidado puede ocupar cantidades
demasiado grandes de memoria). Y esta aplicación se considero
lo bastante frecuente para implementar una abreviatura, de modo
que la expresión anterior es equivalente a:
$ra3d[0][0][0]=1;
Lo cual le da mas claridad de lectura al código (pero debe
tenerse cuidado de no confundirlo con un elemento de un arreglo,
$ra3d es una referencia a un arreglo de referencias y no un arreglo
normal. Por claridad podríamos usar:
$ra3d->[0][0][0]=1;
Ejemplo: A continuación, coloco el listado de un programa
que usa las estructuras de datos que mencionamos anteriormente usando
su potencia lo mas posible sin que pierdan claridad, recomiendo
que no solo se pruebe el programa, sino que se elabore una versión
en la que se exploren los puntos que particularmente les resulten
mas interesantes.
2.2.3.2- Archivos
Uno de los usos mas probados
y comunes de Perl es el procesamiento de archivos de texto para
generar otros archivos (por lo regular de texto) que implican cierto
proceso de los datos leídos originalmente. Además,
Perl no conoce mas entrada que la proveniente de archivos (asociando
la entrada, salida y salida de errores a archivos "de ambiente")
por lo que en cierta medida ya hemos revisado el uso básico
de archivos, solo que ahora le daremos la explicación correspondiente
a las entidades que vimos antes.
Como en cualquier otro lenguaje, el ciclo de uso normal de un archivo
es:
Apertura Mediante "open" inicializa una variable de archivo
Uso Lectura secuencial por líneas
Cerrado Mediante close
Perl tiene implementaciónes para manejar archivos binarios
y archivos aleatorios, pero el uso de archivos de texto secuenciales
es lo mas común en UNIX, por lo que considero a este manejo
como básico y le explico aquí.
Básicamente, se puede decir que hay tres tipos de archivos
que se manejan de modo muy similar:
Archivos comunes
Programas de los que capturamos la entrada o la salida
La entrada, salida o salida estándar de errores.
Estos tres tipos de archivos se manejan igual (con la limitación
de que algunos solo reciben lectura o escritura) y el momento en
que se determina el tipo verdadero del archivo, es en el momento
de la apertura, por lo que ha dedicado una sección exclusivamente
a la apertura mientras que al uso y cierre los he concentrado en
la sección que siguiente a esta.
Inicio
ayudas
|