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
|
|
|