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 |