Descarga la aplicación para disfrutar aún más
Vista previa del material en texto
INTRODUCCIÓN AL LENGUAJE PERL ERL significa Practical Extraction and Report Language, algo así como lenguaje práctico de extracción y de informes. Es un lenguaje creado por Larry Wall (quien, por cierto, es uno de los net-gods más conocidos en la actualidad) con el objetivo principal de simplificar las tareas de administración de un sistema UNIX. En realidad hoy en día, en su última versión, se ha convertido en un lenguaje de propósito general, y una de las principales herramientas de cualquiera que desee gestionar datos web en internet. Es un lenguaje interpretado que tiene varias utilidades, pero está principalmente orientado a la busqueda, extracción y formateado de ficheros de tipo texto. También es muy usado para manejo y gestión de procesos ( estado de procesos , conteo y extracción de parámetros característicos, etc...). Es una combinación de las características de los lenguajes más usados por los programadores de sistemas, como son los shell del sistema operativo UNIX, los utilidad ( que incluye un lenguaje interpretado propio) awk para formateo y tratamiento de texto e incluso caracteristicas de Pascal, aunque su potencia se basa en la similitud con las mejores características del lenguaje estructurado C. En general cualquier utilidad que se necesite realizar en sh, awk, o sed, se puede implementar de una manera mas potente y sencilla mediante el lenguaje PERL. Algunas de las ventajas del uso del lenguaje PERL son las siguientes: • Construcción de pequeños programas que pueden ser usados como filtros para obtener información de ficheros, realizar busquedas, ... • Se puede utilizar en varios entornos, como puede ser Windows 95, OS/2, ..., sin realizar cambios de código, siendo unicamente necesario la introducción del intérprete PERL correspondiente a cada sistema operativo. • También es uno de los lenguajes mas utilizados en la programación de CGI scripts, que son guiones o scripts que utilizan el interface CGI (Common Gateway Interface), para intercambio de información entre aplicaciones externas y servicios de información. Como ejemplo de ello tenemos los programas de búsqueda usados por el browser Netscape. • El mantenimiento y depuración de un programa en PERL es mucho más sencillo que la de cualquier programa en C. Es un lenguaje que hereda estructuras principalmente de los intérpretes de comandos de UNIX, especialmente el csh, y de otras utilidades estándar, como awk y sed. En realidad, puede hacer todo lo que hacen cualquiera de ellos y todos ellos juntos, y la mayoría de las veces de forma más simple, comprensible y fácil de depurar. PERL es un lenguaje interpretado, aunque en realidad, el intérprete de PERL, como todos los intérpretes modernos, compila los programas antes de ejecutarlos. Por eso se habla de scripts, y no de programas, concepto referido principalmente a programas compilados al lenguaje máquina nativo del ordenador y sistema operativo en el que se ejecuta. P PERL es un lenguaje de programación que busca antes que nada el facilitar la elaboración de tareas comunes en sistemas tipo UNIX, donde tradicionalmente las tareas de administración y proceso de datos se realiza con herramientas muy rudimentarias y por demás hostiles al usuario o administrador. Pero que se aplican sobre grandes cantidades de información (por lo regular texto) por lo que se requiere que sean de alto rendimiento. Aunque desarrollado originalmente en un entorno UNIX, actualmente hay versiones para casi todos los sistemas operativos: DOS (por ejemplo, la última versión, OpenDos) Windows NT, Amiga... Los scripts son compatibles entre las diversas plataformas, de forma que es un verdadero lenguaje multiplataforma. Muchos fabricantes lo incluyen en sus versiones de UNIX; también el Linux lo incluye. PERL surgió como una opción para una gran cantidad de herramientas de UNIX en las cuales basa su propia sintáxis, buscando el mínimo coste de su funcionalidad por una máxima facilidad de programación e integración, siguiendo la filosofía de mantener un ambiente que sea capaz de detectar y corregir pequeñas omisiones del programador, y de proporcionarle una forma abreviada de realizar múltiples tareas. En una palabra, es una utilidad que pretende facilitar el proceso de grandes volúmenes de información sin perjudicar el rendimiento. Las plataformas donde PERL se ha desarrollado mas son los servidores UNIX, por sus necesidades de administración y lo robusto de su manejo de memoria y de procesos (requisitos de PERL hacia el sistema operativo) además de la facilidad de PERL para realizar los así llamados CGIs, interfaces para comunicar recursos del servidor con un servicio de internet particular (como podría ser world wide web o gopher), En otras plataformas, PC en particular, se han desarrollado versiones que mantienen un razonable grado de funcionalidad, pero en realidad, el sistema DOS no tiene un manejo lo bastante bueno de los procesos o de la memoria para permitir a PERL dar un buen rendimiento, además de que no es común ver en PC necesidades de administración de la magnitud de un enorme servidor. Sin embargo, puede practicarse la programación en PERL de PC, o incluso elaborar programas en el , sin embargo, es algo que no se ha popularizado hasta hoy. ALGUNAS CONSIDERACIONES SOBRE PERL PERL no establece ninguna filosofía de programación (de hecho, no se puede decir que sea orientado a objetos, modular o estructurado aun cuando soporta directamente todos estos paradigmas de programación), los objetivos que se tuvieron en cuenta al diseñar la sintáxis de PERL fueron la facilidad de aprendizaje y de uso y la claridad de código, las cuales, considero que son necesarias (aunque pueden escribirse programas en PERL complejos e inteligibles si así se desea). Por si fuese poco, PERL no es ni un compilador ni un intérprete, ya que está 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 optimiza (como si fuésemos a elaborar un programa ejecutable) pero es ejecutado por un motor, como si se tratase de un intérprete. El resultado final, es que utilizamos algo que se comporta como un intérprete pero que tiene un rendimiento comparativo al de programas compilados. Sin embargo, ya existen compiladores de PERL con la versión 5. En fin, PERL no nos obliga a nada, pero como es lógico hay ciertas reglas que recomiendo seguir para facilitar nuestro trabajo: Claridad En la mecánica de programación actual, los programas deben de ser entendibles por la persona que nos suceda en tareas de mantenimiento, de lo contrario perjudicamos tanto a nuestros compañeros de trabajo como a nuestra propia libertad para progresar y mantenernos libres de preocupaciones. Indentación Una costumbre ya clásica de la programación, en lo personal, y a lo largo de los distintos programas, es tabular el código dos espacios hacia adelante al abrir cada bloque, y terminar la tabulación al terminar el bloque, de modo que las llaves de apertura y cierre quedan a la vista y en la misma columna, solas en sus renglones (esto incrementa algo el numero de líneas, pero facilita sobremanera la búsqueda y corrección de los diversos bloques de control). Nombres de variables Es conveniente dar la máxima claridad a los nombres de las variables sin hacerlos demasiado grandes, el nombre de los contadores y variables que guardan valores concernientes a un pequeño segmento de código por lo regular son de un par de letras (c1, c2, ... cx para los contadores, s1, s2, etc para cadenas de entrada etc.) mientras que las variables que afectan a diversos segmentos (a modo de regla, que tienen su definición en una pantalla distinta a donde se usan) tienen nombres explicativos que conviene que no excedan los 12 caracteres. Además, los nombres de archivos se usan con mayúsculas (ARCHENT, ARCHSAL, etc) y las clases tienen su primera letra mayúscula. Comentarios Para facilitar la comprensión de un programa no hay nada mejor que explicarlo, y los comentarios son elmedio ideal para hacerlo. Existen por lo menos tres comentarios que muchos consideran que siempre deben incluirse en un programa: qué hace el programa, quién lo escribió y cuándo inicio y terminó de escribirlo, sobre todo en el contexto de una organización. Estos tres simples comentarios pueden hacer la diferencia entre desestimar un programa como indescifrable o dedicarle algún tiempo para revisarlo. Además, se considera prudente comentar dentro del código la forma en que el programa deberá ejecutarse, parámetros, y su sintáxis, así como comentar las estructuras de control como un modo de explicar la funcionalidad al detalle y resaltar con comentarios las funciones que cumplen las variables. Sencillez Es cómodo en ocasiones el comprimir una serie de instrucciones en una sola línea, queda al criterio decidir cuando se gana en claridad con un código mas o menos extenso, pero no debe titubearse en comentar el código que sea complejo. Bases de datos en PERL Lo más fácil es usar el módulo DBI (que, como todos los demás, está en el CPAN), con un driver específico para el gestor de bases de datos, o si hay ninguno específico, y la base de datos está accesible usando ODBC, puede utilizarse con ODBC. En Windows hay un módulo alternativo, específico para ODBC, denominado Win32::ODBC. Con cualquiera de estos dos módulos, se puede usar con cualquier sistema de gestión de bases de datos. En Linux y UNIX, se puede usar con MySQL o MiniSQL, o Postgres. Por último, en Windows se puede usar también Microsoft SQL Server combinado con ODBC. Eso sí, como es inherente a las conexiones ODBC, es una forma menos ágil de gestionar una base de datos. UN PRIMER PROGRAMA EN PERL Como se menciona en la introducción, PERL no obliga a casi nada, así pues, lo que se plantea como estructura básica es más bien una convención que un requisito del lenguaje, a diferencia de Pascal (por ejemplo) PERL no tiene una plantilla para sus programas. Si se adoptan algunos protocolos es sólo por comodidad. Los programas de PERL, por lo general, inician con la línea: #!/usr/bin/perl Esta línea, indica al sistema operativo que lo que sigue es un script de PERL, y que "PERL", el programa con el que debe ejecutarse, está en el directorio "/usr/bin"(la secuencia "#!" es una secuencia que UNIX reconoce, no PERL). Un método alterno, que funciona para otras plataformas, es: en lugar de colocar esa primera línea ejecutamos: PERL nombre_del_script.pl de modo que directamente se ejecuta el intérprete de PERL pasándole como primer parámetro el script a ejecutar (los demás parámetros se tomaran como parámetros al programa). Si se requiere deberá sustituirse "PERL" por la ruta completa del programa y el nombre que el programa tenga. Para los ejemplos sucesivos, se asumirá que se trabaja en un sistema UNIX con el intérprete de PERL en el directorio "/usr/bin". Resumiendo lo anteriormente expuesto, debe saberse que para ejecutar un programa en PERL podemos hacer dos cosas: • Llamar desde la línea de comandos al intérprete PERL, pasando como parámetro el nombre del programa. sun630% perl primer.pl La extensión pl no es necesaria, pero se suele poner. • Añadir en la primera línea del programa lo siguiente : #! /usr/bin/perl Ademas debemos cambiar los permisos del fichero fuente, para poderlo ejecutar. Esto se realiza mediante la instrucción chmod: chmod u+x primer.pl A continuación de la primera linea escribiríamos el guión del programa, y una vez hecho esto simplemente invocaríamos el nombre del programa directamente desde la línea de comandos. sun630% primerl.pl Los caracteres #! sirven para denotar que lo que viene a continuación hace referencia a un intérprete de comandos. Por ejemplo un perl script que mostraría por la pantalla el mensaje HOLA MUNDO se haría de la siguiente forma: #! /usr/bin/perl print "HOLA MUNDO\n"; Este sería uno de los programas más básicos en PERL, por no decir el que más. Pero, ¿funcionan exactamente igual los programas PERL en Windows y en UNIX? En general, sí. En particular, hay algunas cosas que no funcionan de la misma forma: por ejemplo, la orden fork no funciona (salvo en la última versión), el acceso a base de datos no se hace igual (se usa el módulo DBD/DBI en Linux y en Windows, generalmente, el Win32::ODBC, aunque también se puede usar el mismo); para ejecutar un programa en PERL hay que definir una serie de parámetros. Pero en general, cualquier programa que no use ninguna característica específica de un sistema operativo funciona exactamente igual en los dos sistemas operativos. Y si hay alguna duda, se puede insertar código particular detectando el valor de la variable $OSNAME, $^O o $Config{osname}. TIPOS DE DATOS EN PERL En el lenguaje PERL tiene tres tipos de datos: - Escalares - Vector de escalares - Vectores sociativos de escalares El tipo de dato escalar es denotado mediante un nombre de variable precedido del símbolo $, y puede contener un número , una cadena de caracteres, y una cadena de caracteres en la que alguno de los caracteres puede ser un carácter especial. El escalar, es la clase de datos que engloba los tipos convencionales de datos, de modo que podemos decir: $v1="Pikachu"; $v1=100; $v1=89.12; Sin que esto implique ningún cambio en la naturaleza de $v1, en todo momento es un escalar. Aún cuando la compatibilidad de datos enteros y reales es fácil de imaginar, la conversión implícita en el caso de las cadenas no lo es, sin embargo la regla es bastante simple. Por ejemplo: $v1="123y321"; Esto crea un escalar $v1, que contiene la cadena "123y312". Pero ¿qué pasa si le deseamos sumar 4?. PERL, interpreta $v1 como entero (o punto flotante) para esto, toma todos los caracteres del inicio que forman un numero correcto y ese numero es el que interpreta; de modo que: print $v1+1; imprimirá124, y del mismo modo, como ejemplo: $v2="123.123.123"+1 da el valor 124.123 a la variable $v1 (punto flotante). Otro punto importante de las variables en general es que, aunque en ningún momento se declaran como de un tipo o de otro, si se pueden "destruir", o revisar que hayan recibido algún valor en la ejecución del programa, esto se logra mediante las funciones defined() y undef(): defined nos indica si la variable que le pasamos como argumento ha sido definida (es decir, existe en el programa) o no. undef toma una variable y la "elimina" de modo que ya no tiene valor y defined la reporta como no utilizada. Los valores lógicos de verdadero y falso se manejan de modo similar al de C, cualquier valor escalar no nulo o cero se considera verdadero. Debe tenerse cuidado con las cadenas "0" pues si se evalúan como número resultaran en falso aun cuando no son cadenas nulas. Los escalares son los constituyentes de las demás estructuras de datos, por lo que al explicar los arreglos, hashes, referencias y archivos haremos muchas referencias a ellos. Por ejemplo, si queremos definir una variable de tipo escalar llamada numero y que contenga un el número 12 haríamos: $numero = 12; Para almacenar una cadena de caracteres podemos hacer dos cosas: • Definir el contenido entre comillas simples, no interpretandose ningún carácter especial contenido entre ellas, un ejemplo podría ser : $palabra = 'pikachu'; • Definir el contenido entre comillas dobles , interpretandose cualquier caracter especial contenido entre ellas a la hora de la impresión de la cadena, un ejemplo podría ser: $palabra = " pikachu \n"; Por último, podemos definir varias variables al mismo tiempo utilizando los paréntesis por ejemplo: ($palabra1,$palabra2,$palabra3) = ("Pikachu","Espinete","Don Pimpón"); El tipo de dato vector de escalares es denotado mediante un nombre de variable precedido del simbolo @. Un ejemplo de inicialización de una variable de este tipo podría ser: @frutas = ("manzana","pera","naranja","fresa"); El número de elementos menos uno de un vector de escalares se puede obtener mediante el nombre de la variable precedido de los simbolos $#, por ejemplo si queremos obtener el númerode elementos de @frutas haríamos: $numero_de_elementos = $#frutas+1; Para ser más exactos $# nos devuelve el último indice del vector, así, si el valor para el primer indice es 0 el número de elementos - 1 será el último valor permitido para indexar el vector. El acceso a un elemento de un vector se hace mediante un índice numérico de la forma $nom_variable [ indice ] ; asi, si quisieramos acceder al tercer elemento de @frutas haríamos: $2_elemento = $frutas[2]; También podemos acceder a varios elementos de un vector de la forma siguiente: @nom_variable[indice1,...,indicen] Veamos ahora otra instrucción: print @frutas[1,2]; Esto imprimiría el elemento segundo y tercero del vector @frutas. Otra forma de indexar un vector es usando el operador rango .. , si quisieramos imprimir todos los valores desde un indice i hasta un indice j deberíamos utilizar el siguiente formato @nom_variable[i..j], por ejemplo: print @frutas[0..2]; Así se imprimirían todos los elementos del vector @frutas. Por último tenemos también el tipo de dato vector asociativo de escalares, mediante este tipo de datos podemos acceder a un determinado elemento de un vector a través de una clave anteriormente definida, para denotar este tipo de dato debemos preceder al nombre de la variable con el símbolo % . Un ejemplo de definición de claves y valores de un determinado vector asociativo podria ser: %precio = ( "manzana",100,"pera",20,"naranja",30,"fresa",200 ); Si queremos acceder a un elemento de un vector asociativo, debemos seguir el siguiente formato @nom_variable { clave }, un ejemplo podría ser: $numero_de_manzanas=10; $gasto = @precio {"manzana"} * $numero_de_manzanas; Ahora veremos una versión avanzada del HOLA MUNDO.En nuestro primer programa no utilizamos ninguna variable, por lo que para explicar estos conceptos necesitaremos un nuevo programa. Este es una versión personalizada del anterior HOLA MUNDO. #!/usr/bin/perl #Programa Hola Mundo print "Hola cual es tu nombre?:"; $nombre=<STDIN>; chop($nombre); print "$nombre!, bonito nombre, cuantos años tienes?:"; $edad=<STDIN>; print "sabias que te faltan ".(100-$edad)." para tener 100?\nAdios!\n"; Su ejecución genera resultados similares a los siguientes: Hola cual es tu nombre?: Pikachu Pikachu!, bonito nombre, cuantos años tienes?: 6 sabias que te faltan 94 para tener 100? Adiós! En este programa, aparecen muchos elementos novedosos que iremos revisando poco a poco a lo largo de este documento, por el momento, revisemos que hace línea por línea: #!/usr/bin/perl #Programa Hola Mundo Cabecera normal del programa, incluído comentario indispensable. print "Hola cual es tu nombre?:"; Esta línea escribe "Hola cual es tu nombre?:" pero nótese que no escribe una vuelta de carro al final (omite el "\n"). $nombre=<STDIN>; Aquí asignamos a $nombre un renglón escrito por la entrada estándar del programa(el teclado, por lo general). PERL define al "archivo" STDIN como su entrada estándar, y el operador <> que indica la lectura de una línea de un archivo de texto, de modo que <STDIN> indica la lectura de un renglón de la entrada estándar (al menos para el ejemplo). Para fines prácticos, usaremos <STDIN> como la expresión que lee una línea de entrada del usuario desde teclado. chop($nombre); PERL, al leer la línea escrita por el usuario, también toma el enter que el usuario da, de modo que en el ejemplo, la entrada que se da en vez de ser "Pikachu" se puede escribir como "Pikachul\n", (siendo "\n" el carácter de vuelta de carro), la función "chop()" tiene la función de eliminar el último carácter a nuestra cadena, de modo que después de esta instrucción $nombre sólo tiene "Pikachu". Por las características de la lectura de renglones de archivos, chop() es un elemento casi constante en programas de PERL. Si se comenta esta línea, se comprobará que al imprimir el nombre imprime también el retorno de carro avanzando una línea hacia abajo. print "$nombre!, bonito nombre, cuantos años tienes?:"; Esta línea nos muestra como se imprime el contenido de nuestras variables de forma sencilla; notamos que en la cadena a imprimir se encuentra $nombre, el compilador lo interpreta y reemplaza por su valor, (para imprimir "$" se pone "\$"), el resto de la cadena es completamente convencional. $edad=<STDIN>; Esta línea, lee otra línea de texto y la coloca en la variable $edad (con retorno de carro incluído). print "sabias que te faltan ".(100-$edad)." para tener 100?\nAdios!\n"; Esta línea imprime un mensaje que esta dividido en tres partes, la primera y la ultima son cadenas convencionales, que están concatenadas (operador .) con una operación aritmética. Hay que notar que edad era un renglón de la entrada estándar, y no un numero, sin embargo no hay conflicto de tipo al operarlo con un entero, ¿porque? porque los dos, para PERL, son del mismo tipo, son escalares, como ya se ha comentado con anterioridad. Los escalares utilizan un mecanismo de conversión que se emplea para extraer el entero del texto contenido en $edad. Después de un primer encuentro con las variables de PERL, el sentimiento mas probable es el de perplejidad, sobre todo para el programador habituado a trabajar con lenguaje C, donde las restricciones de tipos están bastante delimitadas y cualquier conversión requiere de una función específica. En realidad, las variables de PERL pretenden simplificar el diseño del programa, pero debiendo comprender cómo se pretende facilitar las cosas, para no terminar creando conflictos entre diferentes variables. ARREGLOS EN PERL Los arreglos en PERL son simplemente, arreglos dinámicos de escalares, es decir, se pueden usar cualesquiera elementos en el arreglo y PERL se encargará de hacer al arreglo de la dimensión adecuada. La definición de un arreglo con valores constantes es: @a1=("hola",123,43.2,"adios"); Esta definición, crea el arreglo @a1 con cuatro elementos, dos cadenas, un entero y un real, en realidad, cuatro escalares, para hacer referencia a los elementos escalares de un arreglo se usan los corchetes [] indicando el índice del elemento (de cero al numero de elementos menos uno) de modo que: print "$a1[0]\n$a1[1]\n$a1[2]\n$a3[3]\n"; resulta para el arreglo anterior: hola 123 43.2 adiós Nótese que el elemento de un arreglo ya no es un arreglo, sino un escalar, y debe especificarse como tal, con $ en vez de @. No es lo mismo el escalar a1 que un elemento del arreglo a1. $a1 Es un elemento distinto que $a1[] Por claridad, es recomendable no duplicar nombres de arreglos (o cualquier otra cosa) con escalares, aunque PERL da un manejo independiente a las diversas entidades, de modo que si se hace no habrá quejas de parte de PERL. Es importante señalar que los arreglos y hashes no pueden ser elementos de un arreglo, si se intenta esto, los arreglos o hashes serán "acondicionados" a elementos que se agregan al arreglo. Por ejemplo: (a,b,(c,d),e)==(a,b,c,d,e) Es decir, el arreglo constante a,b, arregló con c,d , e es equivalente al arreglo que contiene a,b,c,d,e. Pues al formar el primer arreglo, el sub-arreglo c,d es "aplanado" a elementos que se agregan al arreglo principal. Algo similar sucede a los hashes. Para hacer arreglos de arreglos o arreglos como elementos de hashes, se utilizan las referencias. HASH O ARREGLOS ASOCIATIVOS EN PERL El Hash, o arreglo asociativo es una ampliación del arreglo, en la que en vez de ubicar los elementos por posición se les ubica por una "llave" es pues un arreglo de parejas ordenadas que se accesa por el primer elemento, el símbolo de los hashes es %, y la forma de declarar un hash con constantes es muy similar a la forma para declarar un arreglo: %h1=("ll1",1,"ll2",2,"ll3",3); Esta declaración crea un hash con tres parejas ordenadas, las llaves son "ll1", "ll2", "ll3", para usarlo se pueden usar expresiones del tipo: $ndx="ll3"; print "$h1{ll1}\n$h1{"ll2"}\n$h1{$ndx}\n"; resultando: 1 2 3 Al igual que en los arreglos, cada elemento de un hash es un escalar, de modo quedebe anteponerse $ en vez de % (pues no estamos haciendo referencia a todo el hash, sino a un elemento escalar del hash), pero a diferencia del los arreglos, en vez de usar [] para indicar el índice se usan las llaves {}. Dentro de las llaves, en el ejemplo, usamos las tres formas principales de dar el índice: ll1 - En esta forma PERL adivina correctamente que ll1 es una cadena y que esta es la llave. • "ll2" - En esta forma decimos explícitamente el valor de la llave deseada. • $ndx- como $ndx="ll3" PERL puede determinar el valor de la llave correcta. Para índices, al igual que para hashes, también puede usarse el valor de variables o de expresiones para especificar el índice. EQUIVALENCIAS DE CLASES Como ya revisamos, al hacer referencia a un elemento particular de un arreglo o hash obtenemos un escalar (en ves de todo el arreglo o hash). Este tipo de "cambios" de clase son el propósito de esta sección, pues pueden resultar algo confusos aunque, una vez comprendidos, dan una buena parte de las características peculiares de PERL. Básicamente, PERL distingue dos tipos de contextos para evaluar una expresión: como escalar y como arreglo. El primero se refiere a las expresiones que han de regresar un escalar (del tipo que sea) como resultado, y el segundo a aquellas expresiones que han de regresar un arreglo o conjunto de escalares como resultado. Muchas expresiones pueden ser evaluadas en ambos contextos y obtener, según el contexto, un resultado distinto, esto lo revisaremos con cuidado conforme vayamos revisando estas expresiones. Revisemos los cambios que ocurren a los datos de una cierta clase cuando los evaluamos en otro contexto: Las transiciones mas utilizadas son las de arreglo a escalar, las de arreglo a hash y de hash a arreglo, la primera porque permite conocer el tamaño de los arreglos y las segundas porque proveen los mecanismos para inicializar los hashes con arreglos constantes y para "acondicionarlos" con fines de almacenamiento e impresión. A menudo, se representa un arreglo con una sola cadena que contiene separadores para los diversos elementos, PERL implementa la función "split" que divide estas cadenas en arreglos, su sintáxis básica es: split($delim,$cadena) Donde $delim es la expresión que representa los delimitadores de elementos y $cadena es la cadena a dividir. Como ya se mencionó, generará un arreglo de cadenas donde los elementos son las subcadenas de $cadena que estén separadas por cadenas $delim. Por ejemplo, una cadena como: $registro="pikachu@pokemon.com"; @reg=split(":",$registro); print "Nombre:$reg[0]\nEdad:$reg[1]\nEmail:$reg[2]\n"; Genera un resultado similar a: Nombre:Pikachu Edad:6 Email:pikachu@pokemon.com No todas las funciones de PERL convierten de igual forma los arreglos en escalares, por lo que debe provarse o investigar primero que efectivamente en el contexto en que hagamos la conversión el resultado sea el deseado. Ejemplos: @arreglo=(1,2,"hola",3,"adios"); Esto inicializa el arreglo @arreglo con los elementos 1,2,"hola",3,"adios", (todos escalares). la notación de los elementos entre paréntesis define un arreglo constante, el equivalente a un numero o cadena constante cuyo valor asignáramos a una variable pero en el contexto de los arreglos. Ahora un ejemplo de hash constante: %hash=("llave1","dato1","llave2","dato2); Arreglo constante a hash Inicializa el %hash con las llaves "llave1" y "llave2" poniéndole como contenidos "dato1" y "dato2" respectivamente. De hecho, no especificamos un "hash constante" como en el caso del arreglo, sino que especificamos un arreglo constante el cual pasa por una transformación de clase para asignarse a un hash, de modo que la expresión es equivalente a: @arreglo=("llave1","dato1","llave2","dato2); %hash=@arreglo; #arreglo a hash Ahora otro ejemplo de cardinalidad de un arreglo: @arreglo=(1,2,3,4); $elementos=@arreglo; En este caso $elemento recibe el valor 4, pues son 4 los elementos del arreglo, nótese que el índice máximo en el arreglo es de solo tres, pues el primer elemento es el elemento 0 y PERL 4 regresa, con esta misma expresión el índice máximo en lugar del número de elementos como PERL 5. Ejemplo de asignación a arreglo constante: ($a,$b,$c)=(1,2,3); Esta expresión es equivalente a: $a=1; $b=2; $c=3; Pero debe examinarse cuidadosamente, el siguiente código: ($a,$b,$c)=(1,2,3); @a=($a,$b,$c); $a=7; $b=8; $c=9; Da al arreglo @a el valor del arreglo constante (1,2,3), y no, como podría pensarse. (7,8,9). Cuando se genera un arreglo constante se evalúan los elementos que lo forman como constantes escalares y se le asigna después, para obtener resultados diferentes se deberá usar un arreglo de referencias. Veamos ahora un ejemplo de arreglos con arreglos: @a=(1,2,3); @b=(5,6,7); @c=(@a,4,@b,8); Estas expresiones generan tres arreglos, (1,2,3), (5,6,7) y (1,2,3,4,5,6,7,8), y no, como podría pensarse un arreglo de arreglos, cuando incluimos un arreglo dentro de otro, PERL "acondiciona" el arreglo insertado como si insertara uno a uno todos sus elementos en la posición indicada del arreglo que ha de contenerlos, para hacer arreglos de arreglos deberemos usar referencias a éstos. OTRAS CONSIDERACIONES SOBRE LOS DATOS En PERL existen formas de hacer determinadas cosas imposibles con otros tipos. Además, Referencias Este tipo de datos es exclusivo de PERL 5, ya que PERL 4 usaba los type globs para realizar algunas de estas funciones, pero el proceso es mucho mas complicado y obscuro. Las referencias son el equivalente lógico de los punteros, son un tipo de dato que no contiene información en sí misma, sino que permite manejar indirectamente los datos contenidos en otra entidad. Las referencias, sin embargo, no forman una clase nueva de datos, sino que son tratados como un tipo más de escalar. La definición de referencias se realiza por el operador referencia "\" (backslash) , funciona de modo similar a "&" en C, y aunque a diferencia de C no hay un operador de de referencia, la sintáxis para acceder al dato original es muy sencilla. A diferencia de C, los objetos que creemos mediante referencias no quedan como cadáveres en memoria, PERL lleva un registro de las diversas referencias a cada elemento en memoria y automáticamente lo destruye cuando descubre que nadie hace ya referencia a él, de modo que pueden usarse las referencias sin miedo, aunque con la precaución necesaria para no perder los datos que se almacenan en ellas. Creación Podemos crear referencias de varias formas, siendo las más sencillas y útiles las que se citan a continuación. Usando el operador de referenciación en una variable, o valor, en el caso de una variable, es crear un medio alterno de acceder al valor de la variable. $rescalar=\$escalar; $rarreglo=\@arreglo; $rhash=\%hash; $rrutina=\&subrutina; Creando objetos "anónimos" que solo pueden ser utilizados por medio de la referencia. Escalares $rescalar=\"hola"; #referencia a la cadena anónima "hola" Arreglos: $rarreglo=[1,2,3]; # referencia al arreglo anónimo (1,2,3) Hashes $rhash={"llave1"=> "dato1","llave2"=> "dato2"}; Nótese que en esta representación usamos además el operador "=>" que indica una pareja de llave y dato, las que se separan por comas; esta notación también es valida para hashes convencionales, pero la claridad que agrega es mejor utilizada al declarar hashes anónimos. Como elementos de arreglos y/o hashes para formar estructuras de datos complejas, al ser escalares, son elementos del arreglo sin mas complicación,de modo que los arreglos a los que hacen referencia se mantienen intáctos. Por ejemplo, para formar un hash que contenga arreglos de nombres de letras: %rhletras={ "latinas"=> ["a","b","c"], "gregas"=> ["alfa","beta","gamma"]}; Esta sentencia forma un hash donde las llaves son cadenas y los datos son referencia a arreglos. Pueden convinarse las referencias a arreglos y a hashes anónimos a voluntad para formar una estructura de datos tan compleja como se desee. Usos De nada sirvenlas referencias si no podemos extraer y modificar los datos contenidos en los elementos señalados por la referencia, en PERL la forma para obtener el valor y para modificarlo es casi la misma, solo las abreviaturas de las referencias para obtener el valor funcionaran de modo distinto cuando tratemos de asignarles valor. Aún cuando PERL tiene varias formas de "referenciar" la información, sólo se discutirán dos por considerarlas las más sencillas. Veamos el uso "simbólico" de las referencias. Por regla general, podemos usar las referencias como si se sustituyeran antes de ejecutar el código (aunque en realidad, no sea así), de modo que el código: $nombre="entero"; $entero=5; $rentero=\$entero; $$nombre=6; $$rentero=7; Efectivamente cambia el valor de $entero de 5 a 6 y despues de 6 a 7, del mismo modo podemos usar las referencias refiriéndonos a cualquier otro tipo. Por ejemplo, para arreglos: $rarreglo=[1,2,3,4]; $$rarreglo[2]="tres"; @$rarreglo=(); Como una forma de abreviar el proceso para referencias a arreglos y hashes, se añadió el operador -> que indica que el escalar es una referencia a hash o arreglo y espera el índice después. Por ejemplo: $rarreglo->[5]="algo"; Esto coloca "algo" como el 6o elemento del arreglo al que hace referencia a $rarreglo. $rhash->{"alfa"}="uno"; Coloca la pareja ("alfa"=> "uno") en el hash al que hace referencia $rhash. Se pueden obtener referencias a referencias, y se pueden hacer arreglos de referencias, de modo que los arreglos multidimencionales se pueden elaborar con la misma mecánica que en C. $ra3d->[0]->[0]->[0]=1; Nótese que al crear perl los arreglos de las dimensiones adecuadas automáticamente no hay problemas de invasión de memoria no reservada (aunque un uso descuidado puede ocupar cantidades demasiado grandes de memoria). Y esta aplicación se considero lo bastante frecuente para implementar una abreviatura, de modo que la expresión anterior es equivalente a: $ra3d[0][0][0]=1; Lo cuál le da más claridad de lectura al código (pero debe tenerse cuidado de no confundirlo con un elemento de un arreglo, $ra3d es una referencia a un arreglo de referencias y no un arreglo normal. Por claridad se puede usar: $ra3d->[0][0][0]=1; CONVENCIONES GENERALES DE SINTÁXIS EN PERL Como ya hemos podido observar, todas las intrucciones de PERL deben deben acabar en ;(al igual que en C y C++) . Por ejemplo: $numero = 2; print $numero; Además, las únicas cosas que deben de ser declaradas en PERL son los formatos de salida o reports y las subrrutinas . Todas las variables creadas y no inicializadas tienen como valor por defecto nulo o cero. Los comentarios deben ir precedidos del símbolo #. Ahora veremos de forma práctica el uso de las sentencias de control condicionales e iterativas que suministra el lenguaje PERL para alterar el flujo de un programa. En primer lugar entenderemos como bloque a todo conjunto de sentencias que se encuentren entre dos llaves, por ejemplo lo siguiente sería un bloque: { $numero=2; print $numero; } Los bloques, además, pueden ser etiquetados anteponiendo a la llave de apertura el nombre de la etiqueta mas dos puntos. En segundo lugar entenderemos como expresión a toda expresión cuya evaluación resulte ser un valor booleano, es decir, verdadero o falso. Hay que tener en cuenta que en PERL se considera como verdadero todo valor no nulo,luego se pueden presentar como expresiones el resultado de una asignación,de una búsqueda etc... Una vez hechas estas consideraciones pasamos a ver la sintáxis de los distintos esquemas de control, que como ya hemos dicho antes pueden ser: • Esquemas condicionales. • Esquemas iterativos. Dentro de los primeros tenemos los siguientes formatos: if (EXPRESION) BLOQUE Un ejemplo de uso podría ser: print " Pensando un número....\n"; $numero = rand(100); print> " Introduce un numero del 1 al 100:"; $entrada = <STDIN>; if($entrada == $numero) {print "Has acertado el numero\n";} if($entrada > $numero) {print "El numero introducido es mayor que el pensado.\n";} if($entrada < $numero) {print "El numero introducido es menor que el pensado.\n";} print" El número pensado era:",$numero; if (EXPRESION) BLOQUE else BLOQUE. Un ejemplo podria ser el siguiente: print" Pensando un número...\n"; $numero = rand(100); print" Introduce un numero del 1 al 100:"; $entrada = <STDIN>; if($entrada == $numero) { print"Has acertado el numero\n"; } else { if($entrada > $numero) { print"El numero introducido es mayor que el pensado.\n"; } else { print "El numero introducido es menor que el pensado.\n"; } } if (EXPRESION) BLOQUE elsif (EXPRESION) BLOQUE .... else BLOQUE. Un ejemplo podria ser el mostrado a continuación: print" ensando un número...\n"; $numero = print(100); print" Introduce un numero del 1 al 100:"; $entrada = <STDIN>; if($entrada == $numero) { print"Has acertado el numero\n"; } elsif($entrada > $numero) { print"El numero introducido es mayor que el pensado.\n"; } else { print "El numero introducido es menor que el pensado.\n"; } En lugar de if podemos usar unless que tiene el significado contrario. Dentro de los esquemas iterativos tenemos: while (EXPRESION) BLOQUE Mientras se cumpla la condición EXP se ejecutará todo lo que haya dentro del bloque. Un ejemplo podría ser: print" Pensando un número ....\n"; $numero = rand(100); $entrada = $numero+1; while ($entrada > $numero) { print" Introduce un numero del 1 al 100, menor que el pensado:"; $entrada = <STDIN>; if($entrada > $numero) { print "El numero introducido es mayor que el pensado.\n"; } } print " EL NUMERO PENSADO ERA:",$numero; print "\n"; En lugar de while podemos usar until, que tiene el efecto contrario a éste. Si además queremos hacer la primera comparación después de la primera iteración, podemos usar un esquema iterativo do BLOQUE until o do BLOQUE while. for (EXPRESION;EXPRESION;EXPRESION) Su uso es exactamente igual que en C; un ejemplo de uso sería: print "IMPRIMIENDO DEL 1 al 100:\n"; getc; for($i=1;$i<101;$i++) { print $i."\n"; } foreach VARIABLE (ARRAY) BLOQUE Con este esquema vamos obteniendo cada uno de los valores que contiene ARRAY y los vamos depositando en la variable VAR. Un ejemplo podría ser: @frutas=("manzana","pera","naranja","fresa"); foreach $fruta (@frutas) { print $fruta."\n"; } Subrutinas Otro aspecto de interés en PERL es la definición y manejo de subrutinas. El formato de declaración de una subrutina es: sub NOMBRE BLOQUE. Por ejemplo : sub HOLA { print "HOLA\n"; } La llamada a la subrutina la haríamos usando do nombre_de_la_subrutina(); o &nombre_de_la_subrutina; Las dos formas producen el mismo resultado con la excepción de que en el caso de do hay siempre que poner los paréntesis, si queremos pasar argumentos debemos pasar los argumentos entre estos paréntesis, y estos serán almacenados en el vector de escalares @_, es decir para saber el numero y el valor de los argumentos pasados a una subrutina hay que leer de este vector predefinido. Un ejemplo podría ser el siguiente: sub imprime { local($cadena)=@_; print $cadena; } &imprime ("HOLA\n"); En el ejemplo anterior se usa la función local(), que sirve para declarar variables locales a la subrutina, por supuesto podríamos haber hecho referencia directamente a el vector @_. El valor devielto por la subrutina es el de la última expresión evaluada, y puede ser tanto un vector como un escalar. También podemos devolver explicitamente un valor usando return, como en C. También resulta interesante la declaración y uso de formatos o reports. Con la definición de un report, estamos alterando el formato de salida de los registros cuando utilizamos la función write. La sintáxispara la definición de un formato es: format NOMBRE = FORMLIST . Si NOMBRE se omite, entonces STDOUT es tomado como el dispositivo de salida. FORMLIST contiene el formato de la salida de la forma: TABULACIÓN_CAMPO1,TABULACIÓN_CAMPO2,...,TABULACIÓN_CAMPON variable1, variable2,.........,variablen El tipo de tabulación se consigue usando los símbolos: • < : tabulación a la izquierda. • > : tabulación a la derecha. • | : texto centrado. Pondremos tantos símbolos como la longitud máxima requerida para representar el valor de la variable asignada a ese campo, además al principio de la definición de los campos de tabulación debe estar el símbolo @. OPERADORES EN PERL PERL soporta una gran cantidad de operadores, la mayoria de ellos heredados del lenguaje C. En PERL los operadores conservan el mismo uso que en el resto de lenguajes, y se utilizan para realizar operaciones aritmeticas, operaciones logicas ..., entre las variables del programa. Los operadores pueden clasificarse en los siguientes tipos: • Operadores de comparación: mediante estos operadores podemos enfrentar dos expresiones, de manera, que dependiendo de su valor se generará un resultado que puede ser lógico o numérico. PERL tiene los siguientes operadores de comparación: • == . Este operador sirve para comparar dos valores iguales, de manera que cuando las expresiones a su izquierda y su derecha son iguales, devuelve un valor lógico verdadero y cuando no lo son devuelve falso: ¡Error!Referencia de hipervínculo no válida. ($var == 3) { ...} en el caso de que el contenido de la variable sea tres se realizan las operaciones entre parentesis. • eq . Es empleado para comparar expresiones no numéricas, esto es, se utiliza de igual manera que == pero para cadenas. • != . Con este operador se comparan cantidades numéricas diferentes. ¡Error!Referencia de hipervínculo no válida. ($var != 3) { ...} si los valores son diferentes se ejecutan la instrucciones entre llaves. • ne . Se utiliza para comparar cantidades no numericas diferentes. Su funcionamiento es similar que el de !=. • < . Verifica el valor de una cantidad numérica con repecto del valor de la expresión de la derecha, de modo que si el valor de esta expresión es mayor que el de la cantidad numérica se devuelve cierto, en caso contrario se devuelve falso: ¡Error!Referencia de hipervínculo no válida. ($var < 3) { ...} ejecuta las instrucciones entre parentesis si el valor de var es menor que tres. • "> . Verifica el valor de una cantidad numérica con repecto del valor de la expresión de la derecha, de modo que si el valor de esta expresión es menor que el de la cantidad numérica se devuelve cierto, en caso contrario se devuelve falso: ¡Error!Referencia de hipervínculo no válida. ($var > 3) { ...} ejecuta las instrucciones entre parentesis si el valor de var es mayor que tres. Los operadores para los terminos menor o igual y mayor o igual son <= y >= respectivamente, y en ambos casos además de el significado de cada término explicado anteriormente, se devuelve cierto si las expresiones son iguales. Como en el caso de las operaciones anteriores, existen equivalentes que se utilizan con las cadenas no númericas para los terminos < y ¡Error!Referencia de hipervínculo no válida.. Estos operadores son: lt que devuelve cierto si el orden de la cadena de la izquierda es menor que el de la cadena de la derecha, y gt que devuelve cierto si la cadena de la izquierda es mayor que el orden de la cadena de la derecha. • cmp . Este termino es utilizado para comparar caracteres, de manera que, retorna 0 si los caracteres comparados son iguales, 1 si la cadena de la derecha se encuentra al comienzo de la de la izquierda, y -1 en el caso contrario: 'one' cmp 'one' DEVUELVE 0 'one dog ' cmp 'one' DEVUELVE 1 'dog one' cmp 'one' DEVUELVE -1 'es diferente' cmp 'one' DEVUELVE -1 • "<=> . Este termino se utiliza para comparar valores numericos, retornando 0 cuando son iguales, 1 cuando el termino de la derecha es menor que el de la izquierda y -1 en el caso contrario. • =~ . Este termino es usado en las expresiones regulares para indicar la presencia de un patrón de compración dentro de una variable que contiene una cadena de caracteres: ¡Error!Referencia de hipervínculo no válida. ($var =~/pepe/) { ...} verifica si la cadena 'pepe' se encuentra dentro de var y si es así, ejecuta el código entre llaves. • !~ . Meditante este operador se verifica la no existencia del patrón de busqueda en una cadena: ¡Error!Referencia de hipervínculo no válida. ($var !~/pepe/) { ...} si la cadena 'pepe' no esta en var se ejecuta el codigo entre llaves. • Operadores de asignación: los terminos de asignación se utilizan en PERL para dar valores a cualquiera de las variables validas en PERL. Existen en Perl los siguientes operadores de asignación: • = . Con este termino se asigna a la variable que se encuentra a la izquierda del operador el valor de la expresión de la derecha. Asi mediante este valor se pueden dar valores iniciales a cualquier variable: $var = 'Buenos dias'; asigna la cadena 'Buenos dias' a la variable var. • =~ . A parte de la función de verificación de existencia de un patrón dentro de una cadena que anteriormente se explicó, este operador dentro de una expresión regular de sustitución se utiliza para sustituir un patrón de comparación por otra cadena: $var =~ s/one/uno/; se reemplaza la ocurrencia de la cadena 'one' por la cadena 'uno'. • Operadores aritméticos: Mediante estos terminos se realizan las operaciones aritméticas necerias para el manejo de las expresiones. A parte de los operadores aritméticos comunes; +(suma), -(resta), *(multiplicación) y /(división), PERL tambien incluye los siguientes operadores: • ** Este término se emplea para obtener la potencia de un valor numérico, ejemplo : $var = 6; $var**2; el valor almacenado en var es 36. • . Este término se emplea para concatenar dos cadenas de caracteres, ejemplo: $var = 'Fulanito '; $var . 'De tal'; var contendrá la cadena Fulanito De tal. • x Este término multiplica n veces la cadena de caracteres especificada, ejemplo : 'd' x 20; expresa una cadena de 20 caracteres d. • % Permite obtener el módulo de la división entre dos números, ejemplo : $var = 5 % 2; el valor que se asigna a var es 1. • | Este término cuando se emplea entre 2 valores numéricos, permite realizar una operación binaria 'o' entre ellos, ejemplo $var = 3 | 2; el valor que se asigna a la variable es 3. • & Este término cuando se emplea entre 2 valores numéricos, permite realizar una operación binaria 'y' entre ellos, ejemplo : $var = 3 & 2; el valor asignado es 2. El operador de asignación ¡Error!Referencia de hipervínculo no válida. está muy relacionado con los operadores aritméticos de modo que PERL permite que se combinen ambos siguiendo este formato general: $variable (operador aritmetico)= expresión; En general lo que se consigue con este formato es realizar la operación aritmetica, y posteriormente asignar el valor a la variable. Así aquí vemos algunos ejemplos de esta combinación: $var = 5; $var += 6; después de esta asignación el valor de var sera 11 (ha sumado 6 al valor anterior de la variable y posteriormente ha asignado el resultado). $var = 5; $var %= 2; el valor actual de la variable sera 1. Operadores lógicos o relacionales: permiten relacionar dos o más expresiones condicionales para determinar si el resultado lógico es falso o cierto. Estos son los diferentes operadores lógicos que emplea PERL: • | . Este operador se utiliza en las ¡Error!Referencia de hipervínculo no válida.como operador lógico 'o', de modo que retorna cierto siempre que cualquiera de los patrónes de busqueda que componen la expresión sea cierto y falso cuando los dos son falsos. Por ejemplo ¡Error!Referencia de hipervínculo no válida. ($var !~/pepe | juan/) { ...} el código entre llaves se ejecuta si en lacadena que se encuentra dentro de la varible existe una ocurrencia igual a 'pepe' o igual a 'juan'. Además de utilizarse dentro de las expresiones regulares, también se utiliza para unir mediante la operación 'o' dos expresiones condicionales. Así por ejemplo: ¡Error!Referencia de hipervínculo no válida. ($var == 6 | $var < 3) { ...} ejecuta el código entre llaves si la variable es igual a 6 o menor que 3. • || . También representa la operación lógica 'o' pero en este caso se utiliza sobre instrucciones no sobre expresiones. • & . Este operador trabaja como un operador lógico 'y' en expresiones regulares, permite confrontar 2 patrones, de modo que para que se produzca un valor cierto se tiene que cumplir la existencia de ambos en la cadena donde se realiza la comparación, en el caso contrario el valor devuelto es falso, ejemplo: if($var =~ /coche & moto/) { ...} el código entre parentesis se ejecuta si dentro de la variable existe una ocurrencia de la cadena 'coche' y otra de la cadena 'moto'. Como en el caso del operador | también se utiliza para relaccionar expresiones condicionales. • && . Al igual que el operador anterior trabaja como un operador lógico 'y', pero con la diferencia de que este operador se emplea sobre instrucciones y no sobre expresiones regulares. • ! . Con este operador realizamos una evaluación negativa de la expresión, ejemplo: if(!$var) { ...} el código entre llaves se ejecuta si la variable var es nulo o 0. Operadores de Archivo: estos operadores se emplean para verificar en el sistema operativo los permisos de un archivo, o su naturaleza de ejecución, etc. A continuación se muestra los diferentes operadores: • -r : indica si el archivo tiene permiso de lectura. • -W : indica si el archivo tiene permiso de escritura. • -T : indica si el archivo es de tipo texto. • -e : indica si el archivo existe. • -z : indica si el archivo tiene tamaño 0. • -s : indica si el archivo es mayor que 0. • -f : indica si el archivo es plano. • -d : indica si se trata de un directorio. • -M : indica el número dias despues de la última modificación • -B : indica si el archivo es binario. • -t : indica si el archivo esta abierto en un terminal. VARIABLES PREDEFINIDAS EN PERL Los siguientes nombres tienen un significado especial en PERL. Solamente se inluirán los más comunes: • $_ contiene el contenido del último registro leido de un fichero. • $. contiene el número de la última línea leida de un fichero. • $/ separador de campo para la entrada. • $, separador de campo para la salida, aplicable a print. • $\ separador de registro para la salida, aplicable a print. • $~ contiene el nombre del formato o report definido para la salida actual. • $^ contiene el nombre de la cabecera de formato o report definido para la salida actual. • $$ número de proceso perl scripts que se esta ejecutando actualmente. • $& representa el valor de la último cadena de caracteres comparada exitosamente. • $` y $' estos dos terminos se utilizan conjuntamente para separar cadenas de caracteres comparadas exitosamente. • $! contiene el valor actual de ERRNO, es decir, el último error acontecido. • $0 contiene el nombre del fichero que hemos dado a nuestro perl script. • $[ contiene el valor del primer indice de una array de escalares, por defecto es 0. • $< uid real del proceso actual. • $> uid efectivo del proceso actual. • $( gid real del proceso actual. • $) gid efectivo del proceso actual. • @ARGV contiene los parámetros pasados a nuestro perl script. • %ENV array asociativo que contiene las variables de entorno bajo el que se ejecuta nuestro perl script. EXPRESIONES REGULARES EN PERL Las expresiones regulares en PERL nos permiten evaluar o comparar la existencia de un patrón de búsqueda en una cadena o un valor determinado; así por ejemplo, si se tiene un archivo de muchas líneas y se quiere imprimir las líneas que tengan en su inicio un determinado carácter, o se desea reemplazar todas las ocurrencias de una determinada palabra dentro del fichero , se deben emplear las expresiones regulares. Se pueden dividir las expresiones regulares en los siguientes tipos: • Expresiones regulares de comparación : Nos permiten evaluar si un patrón de búsqueda se encuentra en una cadena de caracteres, de modo que mediante este tipo de expresiones regulares obtendremos un valor lógico verdadero o falso según se encuentre el patrón deseado. La sintaxis de este tipo de expresiones regulares es la siguiente: valor a comparar =∼ /patrón de búsqueda/; El principal uso de las expresiones regulares de comparación es la formulación de condiciones en cualquiera de las estructura lógica estructuras lógicas permitidas en PERL. Las expresiones regulares de comparación soportan la siguiente opción: • i; formato: /(PATRON)/i. Mediante esta opción se consigue que la comparación entre la variable y el patrón se realize sin importar minusculas o mayusculas. • Expresiones regulares de sustitución: Esta herramienta permite cambiar los patrones de busqueda por caracteres nuevos definidos por el usuario que componen el patrón de sustitución, la sintaxis es la siguiente : valor a sustituir =∼ s/patrón de búsqueda/sustitución/; Dentro de las expresiones regulares de sustitución encontramos las siguientes opciones: • opción: i; formato: (s/PATRON DE BUSQUEDA /SUSTITUCION DE SUSTITUCION/i) : funciona de igual manera que en el caso de una comparación, ignora las mayúsculas en el reemplazo. • opción: g; formato: (s/PATRON DE BUSQUEDA /PATRON DE SUSTITUCION/g) : esta opción permite reemplazar todas las ocurrencias del patrón de búsqueda. En el caso de no emplear esta opción, la sustitución se realizará sólo con la primera ocurrencia del patrón de sustitución. • opción: e; formato: (s/PATRON DE BUSQUEDA/PATRON DE SUSTITUCION/e): con esta opción se puede evaluar la parte de la sustitución (SUSTITUCION),con valores devueltos por una función. • Expresiones regulares de traducción: Este tipo de expresiones regulares tienen una manera de trabajar muy parecida a la de las sustituciones. En este caso se trata de comparar uno a uno los caracteres del patrón de búsqueda con los de la cadena de sustitución, de modo que cada vez que se encuentra una ocurrencia que coincide con uno de los caracteres del patrón se intercambia por su correspondiente en la cadena del patrón de sustitución. La sintaxis general de esta expresion regular es la siguiente: variable =~ tr/(patrón de búsqueda)/(cadena_a_traducir) Las expresiones regulares de traducción no tienen opciones, la busqueda y sustitución se realiza en el contenido de toda la variable. Pasamos a mostrar un ejemplo que ilustre todo lo anteriormente dicho de las expresiones regulares: Supongamos que tene una archivo de tipo texto con el siguiente contenido: tres perros tres gatos y tres elefantes. Las siguientes expresiones regulares casuarán los efectos que se especifican: open(AR,'prueba.prb')|| die"$!\n"; while (<AR>) { if($ ∼= s /tres/ { print "Se ha encontrado la cadena 'tres'";} } El segmento de codigo anterior realiza las siguientes operaciones: abre un fichero prueba.prb de tipo texto y lo asigna a la variable AR, trás lo que realiza un bucle while que permite recorrer todo el contenido del fichero. Dentro de este bucle, utilizando la variable predefinida $_ (que guarda el contenido de la última linea del fichero definido como entrada); observa mediante una condición if si dentro del registro existe una cadena igual a 'tres'. Como se ve dentro de la condición se utiliza una expresión regular de comparación que devolvera cierto si se encuentra la cadena patrón dentro de la variable ( en este caso el contenido de una línea). En el caso de que la expresión regular devuelva cierto se indica que se encontró la cadena buscada. open(AR,'prueba.prb')|| die"$!\n"; while (<AR>) { $ ∼= s/tres/---/g; print; } Este ejemplo, entra de manera similar al anterior dentro del fichero prueba.prb, tras lo que sustituye dentro de este fichero todas las ocurrenciasde la cadena 'tres' por la cadena '---'. Esto se realiza mediante una expresión regular de sustitución. Con esto la salida por pantalla sería la siguiente: --- perros --- gatos y --- elefantes. open(AR,'prueba.prb')|| die"$\n"; while (<AR>) { $ ∼= tr/tre/1234/; print; } La salida por pantalla de este ejemplo es la siguiente: 123s p322os 123s ga1os y 123s 313fan13s. El código anterior realiza una traducción en el contenido de nuestro fichero prueba.prb, el cual es abierto de la misma manera que en los otros casos. Como se ve en el resultado, cada vez que hay una ocurrencia del caracter 't' este se sustituye por '1', cuando aparace un caracter 'r' la sustitución se hace por el '2' y por último cuando aparace un caracter 'e' la traducción lo sustutituye por el tercer valor de la cadena de sustitución, en este caso 3. El caracter de sustitución 4 es ignorado ya que no tiene correspondencia con ninguno de los caracteres del patrón (solo hay tres caracteres en el patrón). open(AR,'prueba.prb')|| die"$\n"; while (<AR>) { $ =~ tr/tre/12/; print; } La salida por pantalla de este ejemplo es la siguiente: 122s p222os 122s ga1os y 122s 212fan12s. Este ejemplo es identico a el anterior pero en este caso sólo tenemos dos caracteres en la cadena de sustitución. Así, cuando el número de caracteres en la cadena de sustitución es menor que el número de caracteres del patrón, las ocurrencia de los caracteres del patrón que no tienen correspondencia con ningún caracter de sustitución, son intercambiados por el último de los caracteres de sustitución. • Caracteres Especiales. Los caracteres especiales en PERL están intimamente relacionados con las expresiones regulares, ya que estos se suelen usar para denotar ocurrencias como fin de linea, comienzo de linea, un tabulador ..., lo cual como se verá es especialmente práctico dentro de la utilización de las expresiones regulares. Estos son los caracteres especiales que pueden utilizarse en PERL: • Carácter: ^ ; comienzo de linea. Con este caracter expresamos el comienzo de una cadena o registro de caracteres. Así por ejemplo supongamos que se quiere escribir una variable si en su parte inicial se encuentra la cadena 'XXX'. El fragmento de código en PERL que realiza esto sería el siguiente: if($var =~ /^XXX/) { print $var; } Como se ve en el ejemplo, las expresiones regulares y los caracteres especiales suelen estar intimamente relacionados. • Carácter: $ ; final de linea. Paralelamente al caracter anterior este expresa el final de una cadena o un registro de caracteres. Asi si deseamos escribir una variable si en su parte final contiene la cadena 'END' se escribiria la siguiente expresión regular: if($var =∼/$END/) { $var; print } • Carácter: ( ) ; parentesis. Estos se utilizan en PERL para delimitar ciertos patrones de comparación, para posteriormente aplicarles un operador de repetición o una referencia de patrón. • Carácter: [ ] ; corchetes. Se utilizan para delimitar dentro de un determinado patrón un conjunto de caracteres que pueden encontrarse dentro de la variable afectada por una expresión regular. Así por ejemplo, supongamos que en una determinada cadena se quieren sustituir todos las ocurrencias de los numeros 1 ó 4 por la cadena 'X_X'. Para realizar esta sustitución se utilizan los corchetes de la siguiente manera: $var = '1sdffl3l54l6y547'; $var =~ s/[14]/X_X/g; $var; print La salida por pantalla del ejemplo sera la siguiente: X_Xsdff1315X_X6y5X_X7 Cuando se utiliza el carácter ^ con los corchetes, queremos decir la no existencia de la cadena que está entre los corchetes. Así si nuestro ejemplo hubiese sido de esta manera: $var = '1s4s547'; $var =~ s/[^14]/X_X/g; $var; print la salida por pantalla sería la siguiente: 1X_X4X_XX_X4X_X • Carácter: - ; guión. Mediante este carácter denotamos un rango de caracteres o números. Asi por ejemplo, si queremos sustituir en una variable o texto todas las palabras minusculas por palabras mayusculas lo realizaremos mediante la siguiente expresión regular que intercambia cualquier ocurrencia de un caracter en minuscula por su correspondiente el mayúculas: $var = tr/[a-z]/[A-Z]/; • Carácter: { } ; llaves. Dentro de una expresión regular representa la longitud de una cadena. Así para referenciar una cadena de caracteres con tres caracteres ? se expresa de la siguiente manera: /?{3}/ • Carácter: . ; punto. Sirve para representar cualquier carácter. Asi supongamos que queremos sustituir los cuatro primeros caracteres de una cadena: $var = 'Paco Gomez'; $var =~ s/.{4}/Manolo/; print $var; así la salida que se obtiene es la siguiente: Manolo Gomez • Carácter: \d . Mediante este caracter se significa la existencia de un digito. Como ejemplo imaginemos que se quieren sustituir todos los dígitos de una variable por el caracter XXX, lo que se hace de la siguiente manera: $var = '1pikachu2'; $var =~ s/\d/XXX/; print $var; la salida por pantalla es: XXXflying burritoXXX Los siguientes caracteres tienen un significado paralelo al anterior por lo que no se darán ejemplos de ellos: • Carácter: \w . Expresa un carácter alfanumérico. • Carácter: \b . Expresa un espacio en blanco. • Carácter: \t . Significa un tabulador. • Carácter: \r . Expresa un retorno de carro. • Carácter: \n . Significa un final de línea. • Carácter: \s . Expresa un separador de cadena de caracteres. Los anteriores caracteres especiales, en su formato en mayúsculas significan lo contrario, esto es, \W expresa un carácter no alfanumérico, \D expresa un valor no numerico ... Por ultimo el carácter \ permite referenciar un caracter especial en PERL como un carácter normal, así por ejemplo la siguiente sentencia: $var =~ s/\\d/XXX/g; nos permite sustituir todas las ocurrencias de la cadena \d por XXX. Si dentro de la expresion regular se hubiese escrito solo \d, la sustitución se realizaría en todos los valores numericos. En general ocurre lo mismo con el resto de caracteres especiales de PERL. • Operadores de Repetición. Como los caracteres especiales, también se encuentran muy unidos a la aplicación de las expresiones regulares. En este caso, este tipo de operadores nos permiten repetir un número determinado de veces una cadena de caracteres dentro de una expresión regular. Los operadores de repetición son los siguientes: • Operador: * ; con él podemos representar un patrón 0 ó más veces. Así supongamos que se quieren sustituir en una cadena todas las ocurrencias de la expresion 'EO' al final de una cadena de caracteres por 'XX',de modo, que a priori no podemos conocer el número de ocurrencias de 'EO'. Para resolver este problema se utilizará el operador * de la siguiente manera: $var = 'EOpikachuEOEOEO'; $var =~ s/(EO)*$/XX/; print $var; La salida de este programa en PERL es la siguiente: EOpikachuXX Como se observa, ha sustituido un número indeterminado de ocurrencias de 'EO' al final de la cadena por una sola ocurrencia de la cadena 'XX'. Si no se hubiese utilizado el operador '*' junto con el carácter especial '$', la sentencia habría sustituido todas las ocurrencias de EO por XX. Como se observa en este ejemlo se utilizan los parentesis para indicar que la operación de repetición afecta a la cadena EO por entero, de no haberse utilizado los parentesis la repetición afectaria unicamente al caracter O. • Operador: + ; este operador funciona de manera similar que el operador '*', pero con la diferencia de que el patrón es representado una o mas veces. • Operador: ? ; mediante este operador representamos una cadena de caracteres opcional dentro de un patrón. Así si se quiere sustituir la cadena 'usted' y su plural por la cadena '---' se puede realizar el siguiente codigo en PERL: $var =~ s/usted(es)?/---/; con esto consiguimos sustituir todas las ocurrencias de la cadena usted o ustedes por'---'. • Referencia a patrones. Se utilizán para referenciar patrones de comparación o sustitución en las expresiones regulares. PERL trabaja con dos tipos de operadores de comparación: • Operador: $1..9 ; sirven para referenciar uno de los patrones de búsqueda de la expresión regular. El número del 1 al 9 representa el patrón al que queremos nos referimos dentro de la expresión regular. Así un ejemplo del uso de este operador se puede observar en este código en PERL que añade el articulo 'El' a un nombre común: $var = 'PERRO'; $var =~ s/(PERRO)/EL $1/; print $var; Como se observa utilizamos la referencia $1 para referirnos al primer patrón de búsqueda (la cadena `PERRO` en nuestro caso) dentro del apartado dedicado a los patrónes de sustitución, de modo que dentro de la sustitución se encuentra el patrón de busqueda. Después de la ejecución la variable $var tiene la siguiente cadena: EL PERRO • Operador: \1..9 ; este operador tiene la misma utilidad que el anterior, esto es, se utiliza para referenciar patrónes de busqueda, pero en este caso la referencia se reliza en la parte de la expresión regular que se dedica a la escritura de patrones de búsqueda y no en la parte dedicada a los patrónes de sustitución, como en el formato anterior. Así para evaluar el principio y el final de una cadena se escribe el siguiente codigo: if($var =~ /^(\w)+.*\1$/); Esta expresión regular de comparación tiene el siguiente significado: mediante la cadena ^(\w)+ nos referimos a todos los caracteres alfanuméricos que forman parte del principio de la cadena contenida en $var, esto es tomo como primer patrón todos los carcteres alfanuméricos de la cadena; con la cade .* referencio un conjunto arbitrario de caracteres de longitud desconocida; con la cadena \1 expreso el primer patrón utilizado y con $ significo que este patrón debe de estar al final de la cadena contendia en $var. En definitiva la expresión regular tomará el valor cierto, cuando la cadena de caracteres contenida en $var tenga la misma cadena de caracteres alfanuméricos al principio y al final. Así por ejemplo, si $var tiene una cadena de caracteres como esta: 'hola juansdfa hola' el valor de la expresión regular será cierto, ya que los espacios en blanco no se consideran caracteres alfanuméricos. ALGUNAS FUNCIONES DE PERL A continuación se describen algunas de las funciones más utilizadas en la programación de un perl script, esto no pretende ser un manual de referencia luego para conseguir el formato puedes usar el comando man perl: • abs: devuelve el valor absoluto de la expresion pasada. • chmod: cambia los permisos de los ficheros dados. • chop: recorta y retorna el último carácter de una cadena. • chown: cambia el propietario de los ficheros dados. • close : cierra un fichero. • cos: devuelve el coseno del angulo dado en radianes. • defined: sirve para comprobar si existe una variable,formato, subrutina,etc.. • delete: borra un valor de un array asociativo a traves de su clave. • die:imprime en la salida del error estandar un mensaje pasado como parametro cuando ocurre un error en la ejecucion de una sentencia. • eof: retorna verdadero si el final del fichero dado. • eval: evalua la expresión pasada como si se tratase de un pequeño programa perl. • exec: ejecuta lo que pasemos como parametro y sale del programa. • exit: hace que salgamos del perl script devolviendo al sistema operativo el valor pasado como argumento. • exp: retorna el numero e elevado a la potencia pasada como parametro. • fileno: devuelve el descriptor del manejador del fichero pasado como parametro. • fork: realiza una llamada fork. • getc: lee el siguiente caracter del fichero especificado. • hex: devuelve el valor decimal del numero hexadecimal pasado como parametro. • index: devuelve la posicion de la primera ocurrencia de una cadena en otra. • int: devuelve la parte entera del parametro pasado. • join: une las cadenas pasadas como argumento con un separador tambien pasado como argumento. • keys: devuelve todas las claves de un array asociativo. • length: devuelve la longitud en caracteres del parametro pasado. • local: declara como locales las variables pasadas como argumentos. • log: devuelve el logaritmo del numero dado. • mkdir: crea un directorio en el camino dado. • oct: devuelve el valor decimal del numero octal pasado como parametro. • open: abre el fichero fichero dado asociandole un manejador de fichero especificado tambien como parametro. • pop: retorna y borra el ultimo elemento del array dado. • print: muestra en la salida standard o en el fichero especificado la expresion dada. • push: añade el valor dado al final del array pasado como parametro. • rand: devuelve un numero aleatorio entre 0 y el valor pasado como argumento. • read: lee un determinado numero de caracteres desde el fichero pasado como argumento. • rename: sirve para renombrar un fichero. • require: sirve para incluir codigo externo en nuestro guion. • return: devuelve un valor desde una subrutina. • rmdir: borra un directorio. • seek: situa un puntero a fichero en un lugar determinado. • select: sirve para seleccionar el manejador de fichero que sera utilizado por defecto para la salida de los comandos o funciones que no especifiquen un determinado manejador de fichero como parametro. • shift: devuelve el primer valor del array dado borrandolo posteriormente. • sin: devuelve el seno del angulo pasado en radianes. • sleep: causa que el perl script o guion se detenga el numero de segundos especificados. • sort: ordena el array dado. • split: divide una cadena en subcadenas segun el separador especificado. • sqrt: devuelve la raiz cuadrada del numero pasado. • system: igual que exec pero no se sale del perl script. • tell: devuelve la posicion actual del puntero a fichero del manejador de fichero especificado. • values: devuelve todos los valores del array asociativo dado. • write: escribe un registro con formato en el fichero asociado a ese formato. Este ha sido un breve repaso a lo que es el lenguaje PERL, su sintáxis, sus funciones y sus características en general.
Compartir