Lenguaje PERL - Carreras de Sistemas - UARG

Anuncio
!
Lenguaje PERL
&
Autor: Juan Esteban Mascareña
Materia: Base de datos
Carrera: Analista de Sistemas
Universidad Nacional de la Patagonia Austral – Año 2002
Lenguaje PERL
Introducción
!
El lenguaje PERL fue creado por el ligüista devenido en programador Larry Wall entre
1986 y 1987 mientras trabajaba un proyecto en la empresa Unisys. Y aunque no tiene
ningún significado especial más que el de perla (por lo valiosa de la herramienta por
supuesto) también PERL puede tomarse como siglas de Practical Extraction and Report
Language o algo así como Lenguaje Práctico de Extracción y de Informes ya que el
propósito original de PERL era el de generar reportes que encontraran errores y los
corrigiera en un proyecto de desarrollo de software que involucraba varios tipos de
máquinas cubriendo los EEUU. Actualmente PERL es desarrollado en forma altruista por
un grupo de personas conocidos como los Perl Porters en una filosofia de lograr un mejor
software gratis que el que se puede esperar por dinero, mientras que el soporte y la
depuración está a cargo de miles de usuarios alrededor del mundo. Además miles de
programadores voluntarios agregan constantemente nuevos módulos y resoluciones en
lenguaje PERL a casi cualquier problema. La fuente principal de información códigos y
módulos se puede encontrar en http://www.cpan.org.
El lenguaje PERL fue pensado para evolucionar, es decir mientras los lenguajes
tradicionales evolucionan lentamente PERL lo hace rápidamente entre versión y versión
para de esta forma satisfacer las necesidades que las nuevas generaciones exigen. De esta
forma mientras que la primera versión apareció en 1988 para comienzos del 2002 ya estaba
disponible la versión 5.6 y se estaba trabajando en la versión 6.
Aunque se utilizó en un primer momento para facilitar las tareas administrativas en
servidores UNIX fue pensado para funcionar en cualquier computadora y en la actualidad
existen versiones para casi cualquier Sistema Operativo y hardware.
&
PERL pidió prestadas características de awk, sed, grep y c-shell (todas herramientas muy
populares en entornos UNIX) y las integró en un lenguaje de alto nivel con reminiscencias
de las estructuras de C y de las primeras versiones de BASIC. Todo esto hizo de PERL un
lenguaje extremadamente potente y versátil.
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). La filosofia de PERL se puede reducir en palabras de su autor a “hay mas de una
forma de hacerlo”.
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
Base de Datos
1
Lenguaje PERL
un rendimiento comparativo al de programas compilados. Sin embargo, ya existen
compiladores de PERL a partir de la versión 5.
El lenguaje PERL posee tres características fundamentales:
• Un gran manejo de cadenas de texto que lo hacen una herramienta muy conveniente
para procesar archivos de texto y generar páginas HTM L.
• El manejo de variables extremadamente potente, ya que no es necesaria ni la
declaración ni el dimensionado, ya que en principio no hay límites al tamaño que
pueden tener.
• Gran portabilidad de código.
&
!
Todas estas características particulares del lenguaje serán explicadas en detalle en este
informe.
Base de Datos
2
Lenguaje PERL
Estructura básica de un programa
Como se menciona en la introducción, PERL no obliga a casi nada, así pues, lo que se
plantea aquí como estructura básica es mas bien una convención más 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 sistema operativo que lo que sigue es un programa en 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, obviamente en Windows esto no tiene
ningún sentido pero para fines de portabilidad es indispensable.
Un método alterno, que funciona para otras plataformas, es: en lugar de colocar esa primera
línea ejecutamos:
perl nombre_del_programa.pl
de modo que directamente se ejecuta el interprete de PERL pasándole como primer
parámetro el programa 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.
Y eso es toda la estructura básica!. Luego viene el código del programa sin ninguna otra
restricción y la última instrucción es el fin del programa sin ningún otro requerimiento.
Por supuesto ahora el primer Programa Hola mundo:
&
#!/usr/bin/perl
# un saludo para el mundo
print "Hola Mundo\n";
Este programa, se escribe como un archivo de texto común, (al que es recomendable
colocarle la extensión ".pl") y se cambian sus permisos para que pueda ser ejecutado (por lo
regular con un "chmod 755 nombre_programa.pl" en sistemas UNIX), para ejecutarlo
simplemente se invoca el nuevo programa "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.
Como se puede intuir la cadena “# un saludo para el mundo” es un comentario que es
ignorado por el lenguaje. La sintaxis de C para comentarios no funciona en PERL, pues se
Base de Datos
3
Lenguaje PERL
usa a "/" para expresiones regulares (como se verá más adelante), ni la de PASCAL ya que
“{...}“ es usado como delimitador de bloques.
El “;” representa como en la mayoría de los lenguajes el final de la instrucción como una
mínima medida de orden.
Así, la ejecución en un sistema UNIX podría verse como:
!
>chmod 755 Hola.pl
>Hola.pl
Hola Mundo
>Hola.pl
Hola Mundo
>
M ientras que en un entorno Windows se puede usar lo siguiente:
>perl Hola.pl
Hola Mundo
>perl Hola.pl
Hola Mundo
>
Obviamente esto se debe hacer en una ventana de M S-DOS y el programa PERL.EXE debe
estar en el PATH de ejecución de comandos (si fue instalado con éxito el intérprete PERL
seguramente esto ya se cumple).
Ejecutando dos veces el programa se pretende mostrar que no es necesario cambiar el modo
de ejecución del programa sino solo una vez.
&
Por último es muy importante recordar que PERL es un lenguaje que distingue entre
mayúsculas y minúsculas en sus identificadores (diferente de PASCAL y similar a C) y no
será lo mismo print que PRINT o Print.
Base de Datos
4
Lenguaje PERL
Variables
Como cualquier lenguaje de programación, PERL posee variables. Sin embargo, las
variables en PERL son algo curiosas y tienen un comportamiento similar al que tienen en
lenguajes de scripts (como los “shells” de UNIX). En PERL, las variables no tienen tipo, o
al menos, no al estilo de los lenguajes tradicionales como C, JAVA o PASCAL.
Las variables no necesitan ser definidas sino simplemente se pueden empezar a utilizar con
solo nombrarlas, además no es necesario el fijar con anterioridad el tamaño de las mismas
sino que ha medida que se le agregan datos estas ocupan el espacio en memoria que
necesitan ya que el dimensionado se hace en tiempo de ejecución (dinámico).
!
Existen tres tipos de variables:
• Escalares
• Arreglos (arrays)
• Arreglos asociativos (hashes)
Las variables escalares empiezan por $
$a = 5;
$b ="xxx";
$c = $a++; # $a++ es como en C osea $a + 1
Un escalar puede tener números, strings u otras cosas mas complicadas como referencias y
descriptores.
Las variables arreglos empiezan por @
&
@a = (95, 7, 'fff' );
print $a[2]; # imprime el tercer elemento: fff
print @a; # imprime: 957fff ...todo pegado
Los elementos de un arreglo son escalares que empiezan por $, los subíndices empiezan por
0 como en C y el escalar $a no tiene nada que ver con $a[ ].
Las variables hashes o arreglos asociativos empiezan por %. Para crear un elemento de un
hash se requiere una lista de 2 valores el primer elemento es la clave y el segundo es el
valor.
%a = ( 'x', 5, 'y', 3); # llena 2 elementos del hash
print $a{'x'};
# imprime: 5
print $a{'y'};
# imprime: 3
Otra forma de asignación de valores al hash se puede hacer con el operador “=>”.
%a = (‘x’ => 5, ‘y’ => 3);
Base de Datos
5
Lenguaje PERL
Si la clave es un string sencillo se puede omitir las comillas o sea $a{x} es lo mismo que
$a{'x'}. Y si se reasigna un elemento se pierde el valor viejo.
%a = ('x', 5, 'y', 3 );
$a{x}=7;
print $a{x}; # imprime: 7
Los elementos se accesan por claves y no hay claves duplicadas.
Valores
En PERL los valores se guardan separados de las variables e incluso cada valor tiene un
contador que indica cuantas variables lo estan usando, y cuando el contador es cero el valor
desaparece.
!
En las variables escalares no hay una diferenciación de tipos estricta ya que puede ser tanto
un número como una cadena de caracteres; PERL convierte entre los distintos tipos cuando
lo necesita, por lo que se puede tratar un número como una cadena y una cadena como un
número.
Los números
Los tipos numéricos no se distinguen entre enteros ni reales y PERL asigna
automáticamente el tamaño que debe ocupar cada valor en memoria. Se puede establecer de
las siguientes maneras:
123456
123456.78
12E-10
0xff
0377
0b011011
4_231_223_232
Entero normal
Real normal
Exponencial
Hexadecimal
Octal
Binario
Subrayado para legibilidad
&
•
•
•
•
•
•
•
Las cadenas o strings
Los strings pueden escribirse con comillas dobles o simples.
$a = "abcd";
$a = 'abcd';
Cuando se usa doble comilla se pueden intercalar variables escalares y arreglos, o sea que
en el resultado final la variable se substituye por su valor.
$a = 'pueblo'
print "hola $a";
print 'hola $a';
# imprime: hola pueblo
# imprime: hola $a
Base de Datos
6
Lenguaje PERL
Una buena pregunta es como se substituye una variable entre letras sin que se altere el
nombre de la variable. Como ser colocar $a antes de una letra como "s".
$b = "abc$as"; # no sirve... trata de substituir la variable $as
$b = "abc${a}s" # substituye correctamente $a
Entre las comillas dobles se pueden también poner caracteres especiales como \n (salto de
linea), \t (tab), \b (backspace), etc.
print "aaa \n";
# salta linea
Para poder colocar caracteres que tienen significado especial en Perl como $, “, \ es
necesario colocar el carácter de escape \ antes.
!
$a = 1234;
print "valor=$a\$";
# imprime: valor=1234$
Entre las comillas simples solo se tiene que usar esto con ' y \.
print 'abc\'s'; # imprime: abc's
Cuando se substituye un arreglo, PERL coloca un separador que es un espacio en blanco.
@a = (95, 7, "fff" );
print "val=@a" ; # imprime: val=95 7 fff
El separador es realmente el valor de la variable escalar $", y esta es una de las variables
especiales en PERL. Y por suerte $" puede ser reasignada.
# imprime: val=95,7,fff
&
$" = ',';
print "val=@a";
Existe una tercer forma de asignar valores de cadena y es con las comillas invertidas. Estas
tiene un comportamiento muy particular que se asemeja al de los shells de UNIX.
$a = `dir`; # $a queda con la salida del comando "dir"
Hay que recalcar que los comandos que se pueden ejecutar son aquellos que tienen dejan la
salida del resultado por cadenas de texto.
Y como en comillas dobles también en comillas invertidas se puede substituir variables,
además en comillas dobles se puede intercalar comillas invertidas que ejecuten comandos
del sistema operativo e inserten su salida en donde se quiera.
Las variables escalares pueden albergar el valor especial undef. Una variable undef no tiene
valor definido. Todas las variables están a este valor por defecto. Se puede así des-definir
una variable con la construcción undef $variable o con $variable = undef.
Base de Datos
7
Lenguaje PERL
Las listas
Cuando se asignan listas como ser (2, 7, 'sss' ) estas varían su comportamiento según si se
asigna a una variable escalar o de arreglo.
$a = (2, 7, 'sss'); # $a queda con el último valor: 'sss'
@a = (2, 7, 'sss');
$a = @a;
# $a queda con el número de elementos de @a: 3
Se debe notar que (2, 7, 'sss') es un valor mientras que @a es un arreglo y recuerdar que las
variables y los valores son 2 cosas distintas.
Existen abreviaturas para algunas listas, como ser:
Operaciones
!
$a = (2..7);
# $a queda con (2,3,4,5,6,7)
$a = ('a'..'e'); # $a queda con ('a','b','c','d','e')
Las operaciones son una de las características más interesantes de PERL, ya que
dependiendo del tipo se hacen conversiones automáticas de tipos. Dependiendo si es una
operación de cadenas o número PERL hará las conversiones necesarias a cadenas o
números respectivamente.
Operadores aritméticos y de bits
Los operadores aritméticos son los clásicos de suma(+), resta(-), multiplicación(*),
división(/), y exponenciación(**); y tienen el comportamiento clásico.
$a = 2 ** 3; # acá $a = 2 * 2 * 2 = 8
&
Existen también algunas opciones sobre la clásica operatoria y se basa en el
comportamiento que tienen en C dichos operadores.
$a =+ 3;
$a =* 3;
$a++;
$a--;
# $a = $a + 3
# $a = $a * 3
# $a = $a + 1
# $a = $a – 1
Los operadores de bits son y lógico (“and” o “&”), el o lógico (“or” o “ |”), el o exclusivo
(“xor” o “^”) y la negación (“not” o “~”). Estos operadores trabajan a nivel de lógica
binaria.
Operadores lógicos
Estos son los clásicos operadores && (AND), || (OR) y ! (NOT) y realizan operaciones
lógicas con sus operandos, devolviendo VERDADERO o FALSO.
Base de Datos
8
Lenguaje PERL
Operadores relacionales
Estos operadores devuelven un valor lógico VERDADERO o FALSO, y su función básica
es la de comparar dos elementos.
Se tienen los operadores para comparar números (similares a los de C) como siguen:
if ($a == $b)
{ print "A igual a B";}
Para comparar strings se usan otros operadores totalmente diferentes:
if ($a eq $b)
{print "A igual a B";}
Operación
Igual
Distinto
M enor
M ayor
M enor o igual
M ayor o igual
!
Acá se tiene la lista de operadores relacionales:
Números
==
!=
<
>
<=
>=
Cadenas
eq
ne
lt
gt
le
ge
Es importante distinguir entre estos dos tipos de operadores relacionales ya que aunque en
PERL se hacen conversiones de tipos en forma automática no tendrán siempre el mismo
resultado.
Existen además dos operadores mas que son una combinación de todos estos, y son el
operador starship (“<=>”) para números y el de comparación (“cmp”) para cadenas.
&
$x = $a <=> $b
# $x queda con -1 si $a < $b
# $x queda con 0 si $a == $b
# $x queda con 1 si $a > $b
$x = $a cmp $b
# $x queda con -1 si $a lt $b
# $x queda con 0 si $a eq $b
# $x queda con 1 si $a gt $b
Operador ternario
Este operador es una abreviatura de las 3 partes que tiene la estructura if (la condición a
evaluar, la acción si es verdadera y la acción si es falsa separadas por ? y :), es muy flexible
pero no es muy bueno para la claridad del código.
Base de Datos
9
Lenguaje PERL
$txt = $a > 5 ? "a es > 5" : "a no es > 5";
print $txt;
Operadores de cadenas
El operador repetir strings "x".
$a = "y";
$b = $a x 5;
# $b queda con "yyyyy"
El operador concatenar strings ".".
$a = "abc"
$b = $a . "def" ; # $b queda con "abcdef"
$ra = \$a;
$rb = \@b;
$rc = \%c;
$rx = \$rb;
!
Referencias y punteros
Las referencias son escalares que apuntan al valor de otra variable. La forma de definir los
punteros entonces se puede ver en el siguiente ejemplo:
# referencia a escalar
# referencia a arreglo
# referencia a hash
# referencia a referencia
Tambien de la misma forma se pueden definir referencias a funciones y referencias a
objetos.
Las referencias interesantes son a arreglos y a hashes. Y ahora se describirá otra forma de
crear una referencias a arreglo.
$rb = [ 'e1', 'e2', 'e3'];
# observar los corchetes en vez de paréntesis
&
En este ejemplo el arrray no tiene nombre y $rb es una referencia a un arreglo anónimo.
De una forma similar se puede crear una referencia a hash.
$rc = { k1 => 'v1', k2 => 'v2' };
# observar las llaves en vez de paréntesis
Igual que antes el hash no tiene nombre y $rc es una referencia a un hash anónimo.
Ahora bien si se quiere accesar los elementos referenciados se deben notar las siguientes
características:
•
•
•
•
${$ra} es la desreferencia de $ra.
@{$rb} es la desreferencia de $rb.
@{$ra} es un error porque $ra apunta a un escalar.
%{$rc} es la desreferencia de $rc.
Base de Datos
10
Lenguaje PERL
Ahora se puede analizar una manera de accesar los elementos de un hash usando una
referencia (muy útil si el hash es anónimo).
print $rc->{a};
Variables especiales
En PERL existen algunas variables con significados especiales. Éstas variables tienen como
función el de dar información y el de modificar en cierto sentido cómo PERL se comporta.
$$
$?
$&
$`
$´
$+
$]
$!
$@
$0
$<num>
Significado
Operando por defecto
Contiene la línea del handler que se leyó por última vez.
Separador de las líneas o campos de la entrada.
Separador de los campos de salida.
Si no es cero, indica que se haga un flush de la salida cada vez que se escriba en ella (en vez
de esperar a que se llene el buffer o a un final de línea).
Identificador del proceso que se está ejecutando.
Contiene el resultado de la última ejecución de un comando a través de comillas inversas o la
función system().
Guarda la cadena que se reconoció del último reconocimiento de cadenas (match).
Contiene lo que precedía al trozo de cadena reconocido.
Contiene lo que sigue al trozo de cadena reconocida.
Contiene la cadena que se reconoció en los paréntesis más exteriores. Por ejemplo, se puede
escribir:
/Fieldname: (.*)/ & & ($fichero = $+);
y $fichero siempre tendrá el último valor reconocido.
Guarda el nombre del script que se está ejecutando.
Guarda la cadena que se reconoció por los paréntesis de más externo a más interno y de
izquierda a derecha (se explicará mas ampliamente en las regex).
Contiene la versión de Perl.
Contiene el último valor de errno.
Contiene el último mensaje de error del compilador (para código generado en el momento de
ejecución y ejecutado con eval().
Contiene el nombre del fichero que se está leyendo cuando se utiliza el operador <>.
Contiene la lista de argumentos de la línea de comandos.
Contiene el ambiente del programa.
Handlers de fichero por defecto.
!
Variable
$_
$.
$/
$,
$|
&
$ARGV
@ARGV
% ENV
STDIN,
STDOUT,
etc.
Base de Datos
11
Lenguaje PERL
Estructuras de control
No se puede pensar en un lenguaje de programación sin estructuras de control. Las
estructuras de control permiten realizar bucles y bifurcar la ejecución del programa
dependiendo de condiciones internas. PERL es muy prolífico en cuanto a estructuras de
control, muchas derivadas de C, y otras propias.
Todas las estructuras de control de C (salvo switch que es similar al case de PASCAL, que
no está explícitamente, pero se puede realizar de muchas formas) están disponibles en
PERL. Todas las construcciones actúan sobre un bloque, que, como en C, está definido por
caracteres “{“ y “}”.
•
•
•
!
Ahora bien, como en C, cualquier expresión tiene un significado lógico, por ejemplo las
asignaciones tienen el valor de lo asignado. Mientras que el valor lógico FALSO está
asociado a lo siguiente:
Los strings "" y "0"
El número 0 o de resultado 0.
El valor "no definido" de una variable, o sea cuando existe la variable pero no tiene
valor.
todo lo demas son valores aceptados como estado lógico VERDADERO.
if,elsif,else
La estructura de un if es la siguiente :
&
if ( .... ) {
......;
......;
}
elsif ( .... ) {
......;
......;
}
elsif ( .... ) {
......;
......;
}
else ( .... ) {
......;
......;
}
Notemos que los elsif y el else van solo si el usuario desea varias preguntas, se podria usar
por ejemplo:
Base de Datos
12
Lenguaje PERL
if ( $edad < 18 )
{
print "Tu eres menor de edad\n";
}
else
{
print "Eres un adulto\n";
}
o:
!
if ( $a == 0 )
{
$ind++;
print "Incorrecto\n";
}
Digamos tambien que aunque sea una instruccion por if debe ir entre llaves.
while y until
La forma del while es :
while ( condicion )
{
....;
....;
}
Lo que esta entre llaves se ejecuta mientras sea veradera la condicion. Por ejemplo:
&
print "Cuantos años tienes?";
$a=<STDIN>;
chop($a);
while ( $a > 0 )
{
print "El año anterior tenias $a años\n";
$a--;
}
La forma del until es :
until ( condicion )
{
...;
...;
}
A diferencia del while el until se ejecuta al menos una vez , y se sigue mientras la condicion
sea falso , es decir es similar al Repeat/Until de Pascal.
Base de Datos
13
Lenguaje PERL
for
La forma general del for es:
for ( exp_inicial; exp_testeo; exp_increm)
{
...;
...;
}
Por ejemplo:
!
for ( $x=0;$x<10;$x++)
{
print "Llevas $x puntos\n";
}
foreach
El foreach de PERL no existe en C pero es muy similar al de C-shell, recibe una lista de
valores y asigna cada uno de los valores de la lista a una variable de lectura. Es
extremadamente útil para recorrer arreglos y hashes. La estructura del foreach es:
foreach $a ( @alguna_lista )
{
...;
...;
...;
}
Por ejemplo:
&
@a=(3,5,7,9);
foreach $x (@a)
{
$y=$x*3;
print "$y\n";
}
Imprime 9,15,21,27.
El uso de esta estructura no se limita a los arreglos sino que también puede ser usada con
los hashes mediante dos funciones que son keys y values. Por ejemplo:
%h = ( x => 5, y => 3, z => 'abc' );
foreach $a (keys %h)
{
print $a;
# Imprime x y z
}
Base de Datos
14
Lenguaje PERL
foreach $a (values %h)
{
print $a;
}
# Imprime 5 3 abc
Extras
Se ha dicho anteriormente que todas las estructuras de control necesitaban de llaves, aunque
solo fuera una instruccion; pero esto es incomodo por ejemplo para los if, es por eso que el
if se puede usar de otra forma, poniéndolo al final de lo que queremos ejecutar lo que se
asemeja bastante al lenguaje natural. Por ejemplo:
print "Aqui es, Paulina" if ( $user eq 'Paulina' );
!
También existe el unless, que hace todo lo contrario del if, es decir, ejecuta la accion si no
se cumple la condicion del final. Por ejemplo:
$b=45 unless ($a < 12 ); # b valdra 45 si a>=12
Y como si esto fuera poco también se lo puede hacer con el while.
($q--,print $q*$q) while $q;
También se permite el uso de operadores or (“||”) y and (“&&”) de manera no permitida en
C.
open (HANDLE,”file”) || die “No puedo abrir el fichero”;
$a > 10 && print “No es válido un valor de $a.”;
Por último existen dos comandos que son last y next, que junto con las etiquetas, permiten
alcanzar funcionalidad extra en los bucles.
&
BUCLE: while ($i < 10)
{
if ($i == $j)
{ last BUCLE;} # sale intespestibamente del bucle
....
}
BUCLE: while ($i < 10)
{
if ($i == $j)
{ next BUCLE; } # va directamente a la próxima iteración del bucle
....
}
Estas dos últimas están censuradas en la metodologia estructurada.
Base de Datos
15
Lenguaje PERL
Subrutinas
Al igual que otros lenguajes, Perl permite al usuario definir sus propias funciones, llamadas
subrutinas. Se pueden colocar en cualquier sitio en el programa, pero se suelen definir
todas juntas o bien al principio o bien al final del programa.
A modo de ejemplo, una subrutina tiene el aspecto:
sub una_subrutina {
print "\n Mi primera subrutina en Perl...\n";
}
!
Comienzan por la palabra reservada sub, a continuación se coloca el nombre de la subrutina
y el bloque o cuerpo.
Para llamarla desde el programa principal, se debe anteponer al nombre de la subrutina el
símbolo &:
# llamada sin parametros
&una_subrutina;
# llamada con un parametro
&una_subrutina("hola");
# llamada con dos parametros
&una_subrutina(5-3, "segundo parametro");
Si se llama a una subrutina con más parametros de los que debe recibir, no se produce
ningún error, simplemente se ignoran los sobrantes.
&
Parametros
Cuando una subrutina recibe parametros, estos son pasados como una lista en la variablearray especial @_. Ese array no tiene nada que ver con $_.
El siguiente programa simplemente imprime la lista de argumentos con que se ha llamado:
sub print_args {
print "\n@_\n";
}
# imprimira "llamada con dos parametros"
&print_args("llamada con", "dos parametros");
# imprimira "llamada con TRES parametros"
Base de Datos
16
Lenguaje PERL
&print_args("llamada con", "TRES", "parametros");
Al igual que otra variable-array, puede ser accedida con la notación de corchetes, mediante
las variables $_[0], $_[1], ..., que nada tienen que ver con la variable $_:
sub print_2_args {
print "Primero= $_[0] \n";
print "Segundo= $_[1] \n";
}
!
Otras variables que no sean las @_, $_[i] o las definidas como locales a que se haga
referencia dentro del la subrutina serán globales, con lo cual si se modifica alguna de ellas,
al salir de la subrutina, se habrán modificado:
sub vars_globales {
$a =~ tr/a-z/A-Z/;
$b =~ tr/a-z/A-Z/;
( $a =~ /$b/ || $b =~ /$a/ );
}
primero se pasan los parametros a mayúsculas y después se comprueba si una contiene a la
otra. Pero al volver de la llamada a la función, las variables que se le pasaron se ven
modificadas:
$a = "liMonaDa";
$b = "lImOn";
$r = &vars_globales;
print "\n$r $a $b\n"; # imprime “1 LIMONADA LIMON”
&
A veces esto nos interesará, pero a veces no. Cuando no se quiera ver modificadas las
variables globales desde dentro de una subrutina, se deben utilizar variables locales.
Si se asigna un valor a una nueva variable dentro de una subrutina, y esa variable no es
local a la subrutina, se creará como global, pudiendo utilizarse al volver de la llamada a la
subrutina:
sub vars_globales2 {
$nueva_variable = "valor";
}
&vars_globales2;
print "$nueva_variable"; # imprime "valor"
Base de Datos
17
Lenguaje PERL
Variables locales.
La variable @_, al igual que $_[0], $_[1], ... son locales a la subrutina. PERL permite el
poder definir en las subrutinas variables locales, mediante la palabra reservada local:
sub vars_locales {
local($a, $b);
($a, $b) = ($_[0], $_[1]);
( $a =~ /$b/ || $b =~ /$a/ );
}
devuelve verdadero si el primer parametro o el segundo esta dentro del otro (o falso en caso
contrario). Esta es la forma de evitar el problema que tenía la subrutina vars_globales. Las
variables locales son útiles para no modificar las variables globales. Al definir las variables
locales se puede asignar el valor en la misma línea con:
!
local($a, $b) = ($_[0], $_[1]);
Valores de retorno
El resultado que devuelve una subrutina es la última cosa evaluada.
Así, la subrutina que se describió antes que imprimía los parametros que recibía, devuelve
siempre un 1 (verdadero), que es lo que devuelve la orden print.
Para devolver un valor, se puede hacer dos cosas:
&
sub maximo {
if( $_[0] > $_[1] ) {
$_[0];
}else{
$_[1];
}
}
$mayor = &maximo(37,23); # devuelve 37
o bien usando la palabra reservada return:
sub maximo {
if( $_[0] > $_[1] ) {
return $_[0];
}else{
return $_[1];
}
}
$mayor = &maximo(37,23); # devuelve 37
Base de Datos
18
Lenguaje PERL
Manejo de archivos
Los ficheros de texto en PERL se tratan básicamente como corrientes de caracteres
(streams), para identificar un determinado fichero dentro del código se utilizan handlers
que apuntan a los mismos. Esto identificadores no van precedidos por ningún carácter en
especial, y por ello se suelen utilizar en mayúsculas. Existen nombres de handlers
especiales predefinidos que son STDIN que representa a la entrada estándar, STDOUT que
representa a la salida estándar y STDERR que es la salida de error estándar.
Como en todo lenguaje en Perl el ciclo de uso normal de un archivo es:
• Apertura mediante open que inicializa una variable de archivo
• Lectura secuencial por lineas.
• Cerrado mediante close.
!
De esta forma lo primero que se hace es abrirlo para luego leerlo:
open(FILE,"file1");
while ( $a=<FILE> )
{
.....;
}
close(FILE);
Lo que se hace en primer linea es abrir el archivo de nombre file1 y a ese archivo le
asignamos el handler: FILE. Luego con el while se va leyendo línea a línea (también se
podría haber hecho asignando una variable de tipo arreglo a <FILE> y se habría leído el
archivo de una pasada). Finalmente algo muy importante, es cerrar el archivo con close.
&
Un problema típico para la portabilidad de código entre plataformas es el delimitador de
directorios usado en el nombre de archivo, mientras en sistemas DOS/Windows se usa la
“\” (ej: C:\Mis documentos\) en sistemas UNIX se usa “/” (ej: /home/juan/) y debe ser
tenido en cuenta cuando se programa con manejo de archivos.
Ahora si se quiere escribir en un archivo.
$file='hola.c';
open (A,">$file");
# Se abre para solo escritura el archivo hola.c
print A "hola\n";
close(A);
Tambien si se desea agregar texto al final de un archivo ya existente:
@l=('a',"\n",'b',"\n");
open(G,">>/user/jperez/d.txt");
# Se abre para escritura pero al final del archivo
Base de Datos
19
Lenguaje PERL
print G @l;
close (G);
En resumen los modos de apertura de un archivo son los siguiente:
• <fichero: abre el fichero para sólo lectura.
• >fichero: abre el fichero para sólo escritura.
• >>fichero: abre el fichero para sólo escritura (al final del archivo o append).
• +>fichero: abre el fichero para lectura y escritura.
• +<fichero: abre el fichero para lectura y escritura.
• +>>fichero: abre el fichero para lectura y escritura (al final del archivo).
• |programa: escribe en la estrada estándar del programa. El handler es de sólo
escritura.
• programa|: lee la salida estándar del programa. El handler es de sólo lectura.
!
Los dos último son especialmente interesantes. Por ejemplo, el comando mail de UNIX
envía correo electrónico a usuarios de Internet. El texto a ser enviado lo acepta a través del
teclado o bien a través de la entrada estándar (como la mayoría de los comandos UNIX).
Así, si queremos que un programa PERL nos envíe su salida, se puede hacer en forma muy
simple algo como esto:
open(RESULTADOS,”| mail [email protected]”)
or die “No puedo enviar mail”;
# Hacer algo ...
# ...
print RESULTADOS “El valor es ....\n”;
close RESULTADOS;
# El correo es enviado!!!!
&
Aunque se ha explicado solamente el uso de archivos de texto pero PERL también permite
el manejar archivos binarios. El uso de los mismos es similar al descripto pero como dichos
archivos no contienen líneas terminadas en “\n” para capturar partes del archivo se utiliza la
función read.
open (FX, "auxytd.bin" );
read(FX, $buffer, 100);
# lee hasta 100 bytes
# retorna el numero de bytes leídos realmente
Base de Datos
20
Lenguaje PERL
Expresiones regulares
Una expresión regular es una forma de expresar gramaticalmente la estructura de cualquier
cadena alfanumérica. Las expresiones regulares de PERL o regex son parientes directas del
comando grep de UNIX con algunas pequeñas modificaciones. Para utilizarlas, se las debe
encerrar entre barras (//). Normalmente devolverá un valor lógico indicando si la variable
sobre la que queremos aplicarla contiene o no el patrón. Si no se indica otra coas, por
defecto comparará la expresión con la variable por defecto $_. Por ejemplo:
/pepe/
devolverá el valor cierto si $_ contiene la cadena pepe.
$cad =~ /pepe/
!
Si se quiere utilizar otra variable diferente a la $_ se debe utilizar el operador =~ , por
ejemplo:
es cierto si la cadena pepe esta incluida en $cad.
Las expresiones regulares son sensitivas a mayúsculas, así, la expresión:
$cad = "Pepe come queso";
$cad =~ /pepe/;
es falsa, ya que $cad no contiene la subcadena pepe, aunque contenga la subcadena Pepe.
El operador que hace lo contrario que el =~ es el !~ , así, la expresión:
$cad = "Pepe come queso";
$cad !~ /pepe/;
&
es cierta.
Construyendo expresiones regulares complejas
La forma en que se puede construir expresiones regulares más complejas que las vistas
hasta ahora (especificadas por una cadena de caracteres simple) es la dada en las siguientes
reglas:
• una expresión regular se cumple para una cadena dada si alguna de las laternativas
de la expresión regular se cumple. Las alternativas se especifican separadas con el
caracter |, se evalúan de izquierda a dechera y se para de evaluar ante la primera
coincidencia.
• una alternativa se cumple si cada item que la compone coincide en el orden en que
los items están especificados.
• cada item esta formado o bien por un modificador o por un átomo cuantificado. Los
posibles modificadores son:
o ^ que indica que debe coincidir al principio de la cadena
Base de Datos
21
Lenguaje PERL
•
&
!
•
o $ que indica que debe coincidir al final de la cadena
o \b que especifica los límites de una palabra
o \B que especifica los límites fuera de una palabra
Los posibles átomos cuantificados son:
o {n,m} el átomo debe aparecer entre n y m veces
o {n,} el átomo debe aparecer al menos n veces
o {n} el átomo debe aparecer exactamente n veces
o * el átomo debe aparecer 0 o más veces (como {0,})
o + el átomo debe aparecer 1 o más veces (como {1,})
o ? el átomo debe aparecer 0 o 1 veces (como {0,1})
Los átomos que podemos utilizar son:
o una cadena tal cual, encerrada o no entre paréntesis
o un . especifica cualquier caracter salvo el retorno de carro
o una lista de caracteres entre corchetes ([ ]) especifica uno de esos caracteres.
Un caracter ^ delante de los corchetes niega la clase.
o se pueden especificar rangos en los corchetes, de la forma a-z
o existen ciertos caracteres especiales:
\n retorno de carro (nueva línea)
\r retorno de carro (vuelta al principio de línea)
\t tabulador
\d un dígito (igual que [0-9])
\D un caracter que no sea dígito
\w un caracter alfanumérico (como [0-9a-z_A-Z])
\W un caracter no alfanumérico
\s un caracter de espaciado (como [ \t\r\n])
\S un caracter que no sea de espaciado
un \0 seguido de un número corresponde con ese número en octal
un \x seguido de un número hexadecimal corresponde con ese
número en hexadecimal
o cualquier otro caracter "escapado" coincide consigo mismo.
o cualquier caracter no mencionado coincide consigo mismo.
De tal forma se pueden plantear algunos ejemplos ilustrativos:
^hola
una "d" seguida de un caracter cualquiera y una "l"
(del, dal, dzl, d5l, etc)
una "f" al principio de la cadena (fofo, farfolla, f35,
etc)
"hola" al principio de la cadena (hola, holita, etc)
e$
te$
una "e" al final de la cadena (este, ese, etc)
"te" al final de la cadena (este, paquete, etc)
d.l
^f
.*
"in" seguido de cero o más caracteres "d" (in, ind,
indd, etc)
Cualquier cadena, sin retorno de carro
^$
una cadena vacia
ind*
Base de Datos
22
Lenguaje PERL
[qjk]
[^qjk]
[a-z]
una "q", o una "j" o una "k"
no sea "q", o una "j" o una "k"
Cualquier letra entre la "a" y la "z"
[^a-z]
[a-zA-Z]
no sean letras minúsculas
una letra minúscula o mayúscula
[a-z]+
una secuencia no vacia de letras minúsculas
Coincide con p.e. "fca", "foca", "flaca", "flor vaca",
etc
f.*ca
f.+ca
fe?a
Coincide con los anteriores salvo con "fca"
Coincide con "fa" y "fea"
^[ \t]*$
una linea en blanco, o combinaciones de espacios y
tabuladores
(pe|hue)cos
(da)+
[01]
\/0
\/ 0
o "pecos" o "huecos"
o da o dada o dadada ...
un "0" o un "1"
una división por 0
una división por 0 con un espacio
una división por 0 con un caracter de espacio
(espacio, tabulador, retorno de carro)
\/\s0
!
lo mismo que [-+]?[0-9]*\.?[0-9]* (números
decimales)
una fecha en el siguiente formato DD/MM/AAAA
( (\d{1,2})\/(\d{1,2})\/(\d{1,4}) ) (13/02/1674 ó 8/2/23 pero también 99/99/9999)
pepe|juan
o "pepe" o "juan"
[-+]?\d*\.?\d*
\/\s*0
una división por 0 con varios espacios
una división por 0 con posibles caracteres de
espaciado
\/\s*0\.0*
una división por 0 con posibles caracteres espaciado
y acepta "0." "0.0" "0.00" etc
&
\/ *0
fia|fea|fua
Coincida con "fia", "fea" o "fua"
f(i|e|u)a
(fia|fea|fua)
Coincida con "fia", "fea" o "fua"
Equivale a los dos anteriores
[fia|fea|fua]
Equivale a [fiaeu]
Los dos últimos ejemplos muestran que se debe ir con cuidado a la hora de colocar las
alternativas en las expresiones regulares. Se suelen usar los paréntesis para encerrar las
alternativas en las expresiones regulares y para agrupar patrones a recordar para después,
mientras que se usan los corchetes para especificar clases.
A veces convendrá utilizar el contenido de una variable dentro de la expresión regular. Así,
dependiendo del valor de esa variable se puede buscar diversos patrones (por ejemplo,
buscar el contenido de la variable $a dentro de la variable $b).
Base de Datos
23
Lenguaje PERL
Pues bien, se puede hacer uso de las variables dentro de las expresiones regulares
directamente, como se ve en el siguiente ejemplo:
#!/usr/bin/perl
$a = <>;
$b = <>;
chop($a);
chop($b);
if( $b =~ /$a/ ) {
print "$a esta incluida en $b \n";
}
!
este programa lee de entrada estándar dos cadenas y comprueba si la primera está incluida
en la segunda.
Pero se plantea un problema... ¿y si la expresión regular es algo más compleja?
Supongamos que queremos comprobar si $a seguida de una "P" se encuentra en $b. En este
caso no podemos poner if( $b =~ /$aP/ ) (porque PERL intentaría buscar en $b el contenido
de la variable $aP, y no el de la variable $a seguida de una "P". En este caso hay que hacer
algo como if( $b =~ /${a}P/ ) (nótese el uso de las llaves rodeando el nombre de la
variable).
Sustituciones
Además de identificar expresiones regulares, PERL puede hacer sustituciones basadas en
los "emparejamientos" identificados en las expresiones. La forma de hacer eso es con la
función s///.
Para hacer una sustitución de loco por Loco en la cadena $cad, se usa:
$cad =~ s/loco/Loco/;
&
y para hacerlo en la cadena $_:
s/loco/Loco/;
Si en la cadena aparece más de una vez la cadena a reemplazar, si no se indica lo contrario,
sólo reemplaza la primera ocurrencia. Para hacer una sustitución global, tras el último /
debemos colocar una g:
$cad =~ s/loco/Loco/g;
La expresion retorna el número de sustituciones hechas, 0 (falso) o mayor que 0
(verdadero). Si se quiere replazar ocurrencias como lOco, lOcO, LoCo, etc por Loco, se
puede hacer:
$cad =~ s/[Ll][Oo][Cc][Oo]/Loco/g;
Base de Datos
24
Lenguaje PERL
o más fácil, se utiliza la opcion i (de ignorar mayúsculas):
$cad =~ s/loco/Loco/gi;
y hace una sustitución global ignorando las mayúsculas. Si lo que se quiere es evaluar algo,
en la segunda parte de la expresión regular, se debe utilizar la opción e.
En el siguiente ejemplo, se lee de entrada estándar (sobre $_) y para cada línea (se supone
que tiene un número real) se realiza una operación matemática, quedando el resultado
almacenado en $_. En este ejemplo se hace uso de una variable especial $& que "recuerda"
cierta parte del patrón correspondiente a una parte de la expresión regular que se haya
encerrado entre paréntesis.
Traducción
!
while(<>) {
s/(\d+\.\d+)/$&*100/e;
print;
}
Para hacer una traducción se utiliza la función tr///. Así, la siguiente expresión reemplaza
cada a por e, cada b por d y cada c por f en la cadena $cad:
$cad =~ tr/abc/edf/;
la expresión retorna el número de sustituciones hechas.
El siguiente ejemplo cuenta el número de asteriscos en la cadena $cad:
$contador = ( $cad =~ tr/*/*/ );
&
El siguiente ejemplo transforma a mayúsculas la cadena $_:
tr/a-z/A-Z/;
Recordando patrones
A veces, en una expresión regular conviene recordar los patrones encontrados para ser
usados posteriormente (en la expresión o fuera de ella). Esto se consigue, encerrando los
patrones a recordar entre paréntesis y referenciándolos mediante las variables $1, $2, ... $9
(de sólo lectura) fuera de la expresión, o con las variables \1, \2, ... \9 dentro de la
expresión.
Por ejemplo, el siguiente programa, sustituye las letras mayúsculas por dichas letras pero
entre asteriscos:
$_ = "Hola Don Pepe";
Base de Datos
25
Lenguaje PERL
s/([A-Z])/\*\1\*/g;
print "$_";
Resultando *H*ola *D*on *P*epe.
En el siguiente ejemplo se utilizan los patrones encontrados fuera de la expresión regular,
mediante la variable $1 para encontrar las palabras repetidas:
if( /(\b.+\b) \1/ ) {
print "encontrada la palabra $1 \n";
}
El siguiente ejemplo intercambia el primer y último caracteres de la cadena $_:
!
s/^(.)(.*)(.)$/\3\2\1/;
El siguiente ejemplo intercambia las dos primeras palabras de la cadena $_:
$_ = "Hola Don Pepe";
s/^([^ ]*) *([^ ]*)/\2 \1/;
print "$_";
Resultando Don Hola Pepe.
Tras el uso de una expresión regular, podemos utilizar las variables especiales $`, $&, $',
que guardan lo que hay antes, lo encontrado y lo que hay después en la cadena:
$_ = "Hola Don Pepe";
/on/;
print "\n $` \n $& \n $' \n";
&
Resultando:
Hola D
on
Pepe
Base de Datos
26
Lenguaje PERL
Algunas funciones y módulos más usados
El manejo de funciones en PERL se asemejan al del BASIC en algunos aspectos y al de C
en otros. Las funciones se pueden usar con o sin paréntisis alrededor de los argumentos y la
única diferencia si se utilizan paréntesis es el aspecto de función (por lo que es
recomendable usarlos para hacer el código más claro).
Como ya se ha visto anteriormente print es utilizada para imprimir cadenas o listas de
cadenas en la salida estándar (STDOUT), pero no se ha descripto nada para obtener cosas
de la entrada (STDIN). La forma más común de hacerlo se puede ver mediante el siguiente
ejemplo:
#!/usr/local/bin/perl
!
print ("Cual es tu nombre?");
$nombre=<STDIN>;
chop($nombre); # saca el enter a la linea leida
if ( $name eq "Juan")
{
print "Hola, Claudio! Como estas!\n";
}
else
{
print "Hola, $nombre\n";
}
La expresión <STDIN> indica que se leerá una sola linea desde la entrada estándar, pero
esto incluye hasta el retorno de carro (“\n”) usado para terminar la linea, y esto puede ser
bastante molesto para manejar en la variable por lo que chop lo elimina.
&
A continuación se describirán algunas funciones muy usadas agrupadas por categorías.
Funciones de strings
chop($a)
length($a)
index($a,$x)
uc($a)
lc($a)
substr($a,$pos,$len)
Borra el último caracter del valor de $a.
$a = "abcdef";
chop ( $a ) ; # $a queda con "abcde";
Muy usado para quitar el caracter "\n" al final de una linea de un archivo texto.
Devuelve la longitud del valor de $a.
$a = "abcdf";
print length ( $a ); # imprime: 5
Devuelve la posición de $x en $a
$a = "abcdef";
$b = index ( $a, "cd" );
print $b; # imprime: 2
Devuelve los caracteres de $a en mayusculas.
Devuelve los caracteres de $a en minusculas.
Extrae un string de otro el 2do parámetro es la posición para empezar el 3er
parámetro es la longitud.
$a = "abcdef";
Base de Datos
27
Lenguaje PERL
Funciones de arreglos:
!
print substr ($a, 2, 3); # imprime: cde
Otro interesante uso de substr es al lado izquierdo de una asignación.
$a = "abcdef";
substr ( $a, 2, 3 ) = "xy"; # cambia "cde" por "xy"
print $a
# imprime: abxyf
sprintf(FORMATO, LISTA) Devuelve la cadena formateada según la cadena FORMATO la cual contiene
especificadores de campos a ser sustituidos por los de la LISTA, uno por
campo. Estos especificadores son similares a los de C y tienen la forma % m.nx
donde m y n son valores de tamaño opcionales cuya interpretación depende del
tipo del campo especificado en x que puede ser cualquiera de los siguientes:
• s
Cadena
• c
Caracter
• d
Número decimal
• ld
Número decimal largo
• u
Número decimal sin signo
• lu
Número decimal sin signo largo
• x
Número hexadecimal
• lx
Número hexadecimal largo
• o
Número octal
• lo
Número octal largo
• e
Número de coma flotante en formato exponencial
• f
Número de coma flotante en formato fijo
• g
Número de coma flotante en formato compacto
$a = 3.1416;
$c = sprintf(“% 1.2f % d”,$a,$a); # c se guarda con “3.14 3”
Devuelve un arreglo después de aplicar la expresion a cada elemento del
arreglo... en la expresion "cada elemento" es $_ .
@a = ('ax'..'bc' );
@b = map uc($_) , @a ;
print "@b"; # imprime: AX AY AZ BA BB BC
Devuelve un subarreglo de @a... que contiene los elementos donde la
expresión es verdadera...
@a = ("a1", "a2", "b1", "b2", "c1", "c2");
@b = grep /^b/, @a;
print "@b"; # imprime: b1 b2 ... los que empiezan por 'b'
El arreglo que devuelve grep se puede tambien usar como un valor
lógico... falso si ningun elemento del arreglo cumple la condición...
devuelve un arreglo ordenado ojo que el ordenado es @b... @a sigue
desordenado... claro que se puede escribir impunemente: @a = sort @a
devuelve un arreglo invertido
@b = reverse sort @a # @b queda con @a ordenado descendente
Devuelve un arreglo que resulta de la división de la cadena en $a por le
expresión en exp.
$a = “nombre=juan”
@b = split (/=/,$a) # @b queda con los elementos nombre juan
@b = map expresion, arreglo
&
@b = grep expresion, arreglo
@b = sort ( @a )
@b = reverse ( @a )
@b = split(/exp/,$a)
Funciones de hash
@b = each ( % a );
@b es una lista de 2 elementos ($key, $value)... correspondiente a un elemento
del hash %a... cuando se llama varias veces con el mismo hash itera sobre todos
los elementos del hash...
while ( ($k, $v ) = each ( % a ) )
{
Base de Datos
28
Lenguaje PERL
print ( "key=$k val=$v \n");
}
Devuelve en @b un arreglo con la lista de todos los nombres de las claves del
hash.
Devuelve en @b un arreglo con la lista de todos los valores correspondientes a
las claves del hash.
@b = keys (%a)
@b = values (% a)
CGI
Una vez que se ha visto el protocolo CGI y que se conocen las posibilidades de PERL,
resulta claro saber por qué se utiliza PERL para la programación CGI. CGI es un protocolo
que se basa en información que se manipula como cadenas de caracteres, y las
posibilidades de PERL en este campo son notables (incluso se podría decir que las mejores
de entre los lenguajes de programación).
!
Desde el punto de vista del programa PERL el protocolo CGI posee dos métodos de
comunicación entre el usuario y el programa, estos son el GET y el POST . M ientras que el
GET le envia los datos del formulario a través de la variable de entorno QUERY_STRING
el POST lo hace a través de la entrada estándar.
Otras variables de entorno disponibles en el CGI son las siguientes:
La dirección e-mail de la persona encargada del servidor.
Identifica al servidor y su versión.
Identifica el nombre DNS del servidor, o, en su defecto, su dirección IP.
Versión del protocolo CGI utilizada, normalmente CGI/1.x.
Muestra el protocolo específico de autentificación.
La longitud del cuerpo del mensaje que envió el cliente. Es utilizado por el
CGI para saber cuando dejar de leer la entrada estándar.
Tipo MIME de los datos del cliente.
El URL del que el script fue invocado.
El método utilizado por el cliente.
El nombre del navegador (user-agent), versión y SO del cliente.
Los datos del form del usuario (si la petición es GET).
Dirección IP del cliente.
Nombre DNS del cliente.
El valor del path completo al script CGI.
Nombre del script.
Indica el puerto al que la petición del cliente se lanzó.
Indica el protocolo que el servidor está utilizando.
SERVER_ADMIN
SERVER_SOFTWARE
SERVER_NAME
GATEWAY_INTERFACE
AUTH_TYPE
CONTENT_LENGTH
&
CONTENT_TYPE
HTTP_REFERER
REQUEST_METHOD
HTTP_USER_AGENT
QUERY_STRING
REMOTE_ADDR
REMOTE_HOST
SCRIPT_FILENAME
SCRIPT_NAME
SERVER_PORT
SERVER_PROTOCOL
Un script CGI contiene las siguientes partes:
1. Decodificación de los parámetros de entrada.
2. Proceso en función de dichos parámetros.
3. Armado de la página WEB de respuesta.
En un método normal de extracción de los parámetros CGI es el siguiente:
#!/usr/bin/perl
# primero se obtienen los datos dependiendo el método usado
Base de Datos
29
Lenguaje PERL
if ($ENV{‘REQUEST_METHOD’} =~ /^GET$/i)
{
# se lee directamente de la variable de entorno
$datos_formulario = $ENV{‘QUERY_STRING’};
}
else
{
# se obtiene de la entrada estandard
read (STDIN, $datos_formulario, $ENV{‘CONTENT_LENGTH’});
}
!
Si el método es POST, la cadena con los datos del formulario se pueden obtener de la
entrada estándar (STDIN) del programa. El tamaño que ocupan los parámetros de entrada se
guarda en la variable de entorno CONTENT_LENGTH. Esta lectura de la entrada estándar
se puede realizar con la función read.
@pares = split(/&/,$datos_formulario);
# luego se separan los nombres de cada parámetro de su valor correspondiente
foreach $par (@pares)
{
# el nombre del valor están separados por “=”
($nombre, $valor) = split(/=/,$par);
# se cambias los espacios vienen como “+”
$valor =~ tr/+/ /;
# se cambian los caracteres especiales que traen la forma “%xx”
$valor =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack(“C”,hex($1))/eg;
$formulario{$nombre} = $valor;
}
&
La cadena que se consiguió antes en $datos_formulario está en formato codificado de URL,
es decir los elementos del formulario estaban separados por “&”, y cada par nombre-valor
está separado por “=”. Además, los espacios están sustituidos por “+” y los caracteres
especiales por “%xx”, donde “xx” son dígitos hexadecimales que contienen el valor ASCII
del carácter que representan. El código anterior genera un hash (%formulario) cuyas claves
son los nombres de los elementos del formulario, y los valores, los que estos guardan.
Ahora el programa CGI debe generar una respuesta. Esta respuesta debe ser una página
HTML legible por el browser (o cualquier otro tipo de fichero, siempre que especifiquemos
su tipo MIME).
Lo que el browser recibirá como respuesta es lo que se escriba por la salida estándar. El
servidor WEB se encarga de redireccionar la salida del programa hacia el cliente de vuelta.
El servidor, además completa el conjunto de headers de respuesta si es que el programa no
los ha generado. Aún así, hay un header que es interesante proporcionar: el tipo MIME.
Por ello, lo primero que debe escribir en su salida estándar un programa CGI es el tipo del
documento a enviar seguido de todos los comandos correspondientes al lenguaje HTML.
Base de Datos
30
Lenguaje PERL
# el identificador del tipo
print “Content-type: text/html\n\n”;
# ahora se hace la página propiamente dicha en código HTML por
# la salida estándar
print “<HTML>\n”
print “<HEAD>\n”;
print “<TITLE>Bienvenido</TITLE>\n”;
print “</HEAD>\n”
print “<BODY>\n”
print “<H1>Bienvenido ${formulario{‘nombre’}}</H1>\n”
print “</BODY>\n”;
print “</HTML>\n”;
#!/usr/bin/perl
use CGI;
!
Para facilitar todos estos problemas es que a partir de la versión 5 de PERL se cuenta con el
módulo CGI que se encarga de facilitar todo el trabajo de conexión con el protocolo CGI.
En dicho módulo se pueden encontrar fuciones para obtener los parámetro de entrada, crear
tags HTML, administrar cookies, etc. Existen dos formas de usar este módulo la orientada a
objetos y la estructurada o de funciones. Acá se presenta la versión en objetos del mismo
problema resuelto en el ejemplo anterior:
$q = new CGI;
$nombre = $q->param(‘nombre’);
print $q->header;
print $q->start_html(‘Bienvenido’);
print $q->h1(‘Bienvenido $nombre’);
print $q->end_html;
&
Como se podrá ver el uso es muy sencillo y simplemente es necesario la inicialización de la
clase ($q para nuestro ejemplo) y luego se tiene el elemento param todos los elementos del
formulario de entrada ($q->param). Las funciones restantes equivalen a los tags HTM L
que se ingresan manualmente en el primer ejemplo.
DBI
El acceso a base de datos en PERL se debe hacer a través de módulos especializados,
aunque existen varios específicos según el DBMS (Gestor de Base de Datos) de que se
trate, como ser Win32::ODBC para DBM S bajo servidores Windows o Pg para
PostgreSQL, a partir de la versión 5 se dispone de la interfaz genérica DBI/DBD (Database
independant interface/Database driver). Con esta interfaz se pueden escribir aplicaciones de
acceso a base de datos independientemente del DBM S. Es necesario recalcar que lo que
provee esta interfaz es un conjunto de métodos, variables y convenciones para brindar una
interacción consistente entre el programa PERL y el DBM S usado, no así un lenguaje único
de consulta (SQL) que dependerá del motor en cuestión que se esté usando. Así cambiando
Base de Datos
31
Lenguaje PERL
!
sólo el driver DBD se puede acceder a bases de datos Oracle, Sybase, ODBC, PostgreSQL,
M ySQL, etc, a través de la interfaz común DBI.
Ahora se presentará algunos ejemplos del uso de DBI:
#!/usr/bin/perl
#Usamos las librerias de acceso a BD
use DBI;
my $base_datos="ce";
#Nombre de las base de datos
my $usuario="root";
#Usuario de la BD
my $clave="richal";
#Password de la BD
my $driver="mysql";
#Se utiliza el driver de mysql
my $dsn= “dbi:$driver:$base_datos”;
&
#Se conecta con la BD
my $dbh = DBI->connect($dsn,$usuario,$clave);
Este es un ejemplo de conexión normal a una base de datos mediante la directiva connect
en donde se debe fijar el DBM S a usar, la base a consultar y el nombre y contraseña del
usuario que hace la consulta (hay que recordar que algunos DBM S poseen reglas muy
estrictas sobre lo que pueden hacer los usuarios y poseen tanto restricciones como
permisos). Por último se hace notar que el $dsn puede tener otros dos parámetros que le
permiten comunicarse con DBMS que no son locales con el programa PERL que son
hostname y port de la forma que sigue:
my $dsn= “dbi:$driver:$base_datos:$hostname:$port”;
donde $hostaname puede ser un número de IP o DNS del servidor y $port es la dirección
del puerto por donde se realizará la consulta. Si se ignoran estos parámetros se utiliza por
defecto el localhost o 127.0.0.1.
Base de Datos
32
Lenguaje PERL
Para realizar consultas se puede hacer mediante los métodos prepare y execute de la
siguiente manera:
#Se prepara la sentencia
my $sth = $dbh->prepare("SELECT id,nombre FROM articulos;");
#Se ejecuta la sentencia
$sth->execute();
Y ahora se puede pueden recuperar los datos obtenidos mediante el método fetchrow_array
de la siguiente manera:
!
#Se extraen los datos. Y se imprime tupla a tupla.
while ( @tupla=$sth->fetchrow_array())
{
print "Código:$tupla[0] Nombre: $tupla[1]\n";
}
#Se liberan los recursos ocupados por la sentencia (opcional)
$sth->finish();
Ahora bien en el lenguaje SQL no son solamente consultas sino que también hay
operaciones sobre las tablas como modificaciones, actualizaciones, agregados de registros y
borrados. Este tipo de operaciones se realizan mediante el método do y para agregar un dato
a la tabla se puede hacer de la siguiente manera:
$resultado = $dbh->do ("insert into $tabla values (100,'Melocotones',1.2);");
Luego de realizar todo lo que se debía hacer es necesario desconectarse del DBM S usado
con el siguiente código:
$dbh->disconnect;
&
Todas las operaciones que se hacen mediante el estos comandos pueden resultar erroneas
por distintos motivos como ser que la base no existe, el comando no es reconocido por el
DBMS, etc, todos estos errores se registran en la variable $DBI::err (código numérico) y
$DBI:errstr (una pequeña cadena descriptiva) que contienen el estado de error para el
último comando enviado al DBMS y deben ser verificados constantemente para saber si el
comando fue ejecutado con éxito. Se debe hacer notar que tanto los códigos de error como
las cadenas descriptivas del mismo son generadas por los DBM S y no por DBI por lo
varian de motor en motor.
Ahora bien las operaciones de base de datos pueden llevar su tiempo dependiendo del
DBMS y el tamaño de las tablas que se utilizen y si el servidor es local o no, esto es
especialmente notable en la etapa de conexión por lo que es muy recomendable hacer la
conexión al comienzo y desconectarse recién cuando ya no se tenga nada que hacer.
Anteriormente se a mencionado a ODBC sin mayores explicaciones, en esta parte se haran
algunas precisiones sobre lo que es y para que sirve.
Base de Datos
33
Lenguaje PERL
ODBC es un interfaz que permite a los programadores Windows abstraerse del Sistema
Gestor de Base de Datos (DBM S) específico que se esté usando, permitiendo la interacción
con los datos a través del SQL de ANSI (que es independiente del motor DBM S usado).
Por lo tanto, ODBC es independiente del lenguaje, de la aplicación y del DBM S. ODBC
maneja conjuntos de datos (data sources) a los que se asigna un nombre (DSN, data source
name). Una aplicación puede crear tantos conjuntos de datos como quiera. Un conjunto de
datos puede contener tablas, índices, etc.
Por lo tanto, lo primero que tenemos que hacer es crear un data source para nuestra
aplicación. Esto se puede hacer de dos maneras: bien “a mano”, bien de forma automática
por un programa. Si lo hacemos a mano, debemos elegir, del panel de control, el ícono
Win32 ODBC.
!
Si pulsamos, entramos en el administrador ODBC. Aquí se debe seleccionar la pestaña de
“DSN de usuario”. Se debe elegir “Agregar...” para crear un nuevo origen de datos para
nuestra aplicación. Una vez aquí, se tiene que elegir un driver para el origen de datos que
puede ser el de Access , SQL Server, MySQL, etc. Los drivers pueden ser locales o remotos
(se conectan a un servidor remoto) e indican que manejador de bajo nivel se encargará de
los datos en última instancia.
De esta forma para conectarse con una base de datos mediante ODBC se puede hacer los
siguiente:
$dbh = DBI->connect(“dbi:ODBC:$base”,’’,’’);
&
donde $base contiene el nobre de la base creada con anterioridad. Lo demás es similar a lo
explicado anteriormente solo que las consultas se deben hacer siguiendo el ANSI-SQL y no
el SQL propio de cada DBM S que se acceda mediante ODBC.
Base de Datos
34
Lenguaje PERL
Bibliografia y sitios web utilizados
!
• “Perl, CGI, and Javascript” por Autores varios, 2000, Ed. Sybex. Contiene una muy
buena explicación de cómo utilizar el Perl con servidores Web para aplicaciones CGI y
una buena referencia del lenguaje y de algunos módulos (no está el DBI pero si
Win32:ODBC). Disponible en biblioteca UNPA-UARG.
• “Programming Perl” por Larry Wall, Tom Christiansen y Jon Orwant, 3ra edición de
2000, O’Reilly & Associates. Es una excelente presentación del lenguaje PERL escrita
por su mismísmo creador en forma amena y divertida. La primera edición corregida de
1991 se puede encontrar en biblioteca UNPA-UARG.
• Los sitios oficiales (http://www.perl.com y http://www.cpan.org).
• Páginas del manual oficial PERL.
• Curso de Perl por Mauricio A. Vazquez.
• “Programación para Internet: PERL y CGI” por Diego Sevilla Ruiz, 1999. 7
Otra Bibliografia
&
• “Perl sin errores” por M artin Brown, 2001. Es un libro orientado a la depuración de
errores en programas Perl y requiere de un conocimiento previo del lenguaje. Se
encuentra disponible en biblioteca UNPA-UARG.
• “Learning Perl” por Randal Shwartz y Phoenix, 3ra edición de 2001, O´Reilly &
Associates. Es la mejor introducción disponible al lenguaje y conocido como referencia
indispensable.
• “Perl cookbook” por Tom Christiansen y Nathan Torking Ton, 1998, O´Reilly &
Associates. Es la mejor referencia avanzada con recetas y HOWTOs muy útiles además
de una referencia muy completa de los módulos estándar.
• “Learning Perl on Win32 Systems” por Randal Schwartz, Erik Olson y Tom
Christiansen, 1997, O´Reilly & Associates. Es la adaptación del libro “Learning Perl” a
servidores Web que corren bajo Windows NT.
Base de Datos
35
Descargar