! 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