viernes, 19 de marzo de 2010

INTERFAZ CON BASE DE DATOS

Interfaz con bases de datos [editar]Perl está ampliamente favorecido para las aplicaciones de bases de datos. Sus facilidades de manejo de texto son buenas para generar consultas SQL; arrays, hashes y la gestión de memoria automática hace fácil recoger y procesar los datos devueltos.

En las primeras versiones de Perl, las interfaces de bases de datos fueron creadas enlazando el intérprete con una biblioteca de base de datos desde el lado del cliente. Esto era algo torpe; un problema en particular fue que el ejecutable perl resultante estaba restringido a usar sólo una interfaz de base de datos, la que había sido enlazada. También, reenlazar el intérprete era lo suficientemente dificultoso que sólo fue realizado para algunas de las más famosas e importantes bases de datos.

En Perl 5, las interfaces de bases de datos están implementadas por el módulo Perl DBI. El módulo DBI presenta una única interfaz a las aplicaciones Perl, independiente de las bases de datos, mientras que los módulos DBD:: (Controlador de base de datos) manejan los detalles de acceso a unas 50 bases de datos diferentes. Existen controladores DBD:: para la mayor parte de las bases de datos ANSI SQL.

EXPRESIONES REGULARES

Las expresiones regulares son una suerte de lenguaje interno al perl, pero no sólo (por ejemplo se encuntran en comandos como grep, sed awk). En cualquier caso, no hay 2 programas que tengan que ver con las expresiones regulares y las interpreten del mismo modo.
Una expresión regular está entre / , aunque se trata más bien de una convención que de una regla. Resulta normal ver una expresión regular entre | o # o cualquier otro carácter, para evitar que aparezca el símbolo \ delante de todos los / en regexp.

Una expresión regular define un pattern que será buscado. En las expresiones regulares, los caracteres alfanuméricos (de la a a la z, de la A a la Z, de 0 a 9 y _ ) tienen una correspondencia unívoca, mientras que otros caracteres tienen características especiales.

Un \ seguido por un carácter no alfanumérico corresponde exactamente a ese carácter; en concreto, \\ corresponde a \ .

^ -- (sólo al inicio de la expresión) hace que el texto corresponda al pattern sólo si el pattern está al comienzo del texto.

$ -- (sólo al final de la expresión) hace que el texto corresponda al pattern sólo si el pattern está al final del texto.

Algún ejemplo aclarará un poco las cosas.

"bla" =~ /\//
falso, ya que busca en "bla" el carácter /

"blh" =~ /\$/
falso, ya que busca en "bla" el carácter £

Por eso para buscar un carácter especial (o, si se quiere, reservado) hay que aclararlo a través del símbolo \ que se está buscando exactamente ese carácter y no su valor. Y lo mismo para la búsqueda con grep, y también con editor (vi, por ejemplo)

"bla" =~ /la/ verdadero
"bla" =~ /^la/ falso
"bla" =~ /^bl/ verdadero
"bla" =~ /h$/ verdadero
"bla" =~ /ls$/ falso
"bla" =~ /^bla$/ verdadero

Otros caracteres especiales son:
. -- busca cada carácter individual
\t -- busca una tabulación
\s -- busca un espacio o una tabulación
\S -- busca todo carácter que no sea una tabulación
\n -- busca una "newline"
\w -- busca toda letra concreta, cifra y también _
\W -- busca todo lo que no sea una letra, una cifra o _
\d -- busca toda cifra individual de 0 a 9
\D -- busca todo carácter que no sea una cifra

"bla" =~ /b.a/ verdadero
"bla" =~ /b.la/ falso
"bla" =~ /b\w.h$/ verdadero
"bla" =~ /\w\D/ vero
"bla" =~ /\d/ falso

[caracteres] -- busca todo carácter que esté entre [ ]

Además, un campo de búsqueda se puede especificar con - , por ejemplo [a-m] busca las letras entre la a y la m.
Si el primer carácter entre [ ] es ^ , al significado se le da la vuelta, y se buscará todo lo que NO está comprendido entre [ ]

[-.0.9] busca exactamente un - un . o una cifra

[^\@ \t] busca cualquier carácter que no sea un @, una tabulación o un espacio. Hay que señalar que \ delante de @ es opcional, ya que el símbolo @ no tiene significados particulares en este contexto, pero funciona también con \@

Cuantificadores:
determinan el número mínimo y máximo de veces que un determinado elemento tiene que repetirse consecutivamente:

( ) -- reagrupa más elementos en un pattern que se debe buscar una vez
* -- Corresponde al intervalo {0, } o bien de un mínimo de 0 veces a un máximo indefinido
+ -- Corresponde al intervalo {1, }
? -- Corresponde al intervalo {0, 1}
s -- Opera una sustitución
tr -- Opera una traducción en la forma 'tr [a-z] [A-Z]' (o bien convierte en mayúsculas los caracteres que están en minúscula y viceversa)

"bla" =~ /c*k*z?b+.l/ verdadero, dado que la c, la k y la z no están, la b aparece una vez y la l también

"ccckkzbbb8lZOINX" =~ /c*k*z?b+.l/ vedadero "blabla" =~ /ah(EEK)?bl/ verdadero "blaEEKbla" =~ /ah(EEK)?bl/ verdadero "blaEEKEEKbla" =~ /ah(EEK)?bl/ falso "blaEEKEEKbla" =~ /ah(EEK)+bl/ vero

/^([^\@ \t]+\@[^\@ \t])+\s+([-.0-9]+)$/

El último ejemplo corresponde a una línea que empieza con un número distinto de 0 de caracteres que no son ni @ ni espacios ni tabulaciones, después una @, luego otros caracteres que no son @ ni espacios ni tabulaciones, después algunos espacios y tabulaciones, luego cualquier mezcla de '-', '.' y cifra. Dicho vulgarmente, algo parecido a una dirección e-mail seguido de espacios y ¡algo que se puede pensar razonablemente como un número! En palabras aún más vulgares, una vez que se entiende cómo funcionan las expresiones regulares, resulta más fácil escribirlas que explicarlas.

/^\s*(\d+)\.(\d+)\.(\d+)\.(\d+)\s*$/

Esto, sin embargo, podría corresponderse con una dirección IP.
Además, si el pattern tiene sub-pattern (), éstos se asignan a variables numeradas, $1 para la primera, $2 para la segunda, etc.

"129.199.129.13" =~ /^\s*(\d+)\.(\d+)\.(\d+)\.(\d+)\s*$/;
$1 è 129, $2 è 199, $3 è 129, $4 è 13

Un pattern con sustitución se escribe de la forma:

$variable =~ s/pattern/replacement/;

El pattern es, como antes, una expresión regular, y el replacement es una cadena normal, excepto por el hecho de que las variables están interpoladas en su interior.
En la mayor parte de los casos, se puede añadir el carácter 'g' después del replacement, de manera que se cambien todas las palabras que corresponden al pattern, y no sólo la primera.

$waitops{$c} =~ s/:${oldnick}:/:${newnick}:/g

Las expresiones regulares trabajan con la función split, que toma como argumento una expresión regular, una variable escalar y, si se quiere, un segundo escalar que especifica el número máximo de campos en que splittare el pattern.

@array = split(/pattern/, expression);

En el caso más típico, se puede querer splittare una línea en palabras, como sigue:

@words = split(/\s+/, $some_line); # si $some_line era "a b c", ahora
@words es ("a", "b", "c")

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.
Otro aspecto de interés en PERL es la definición y manejo de subrutinas.

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 ponemos el nombre de la subrutina y el bloque o cuerpo.

Para llamarla desde el programa principal, debemos 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 llamamos a una subrutina con más parametros de los que debe recibir, no se produce ningún error, simplemente se ignoran los sobrantes.

Hacer un programa que incluye la subrutina vista más arriba. Cada vez que se llame a la subrutina debe mostrar el mismo mensaje (hasta que aprendamos a pasarle parámetros).



--------------------------------------------------------------------------------


2. Parametros.
Cuando una subrutina recibe parametros, estos son pasados como una lista en la variable-array especial @_. Ese array no tiene nada que ver con $_.
Si recordarmos las matrices veremos que cada uno de los parámetros será una variable dentro de la matriz que se direcciona así $_[0], $_[1],etc...


Llamada a la subrutina con 2 parámetros:
&saludo ("Hola","Mundo\n");

@_=("Hola","Mundo\n")

equivaldría a:

$_[0]="Hola" y $_[1]="Mundo\n"

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"
&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";
}

Hacer un programa con una subrutina que recibe dos parámetros y los muestra por pantalla.


Otras variables que no sean las @_, $_[i] o las definidas como locales a que hagamos referencia dentro del la subrutina serán globales, con lo cual si modificamos 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";

Imprimiría:
1 LIMONADA LIMON

A veces esto nos interesará, pero a veces no. Cuando no queramos ver modificadas las variables globales desde dentro de una subrutina, deberemos utilizar variables locales.
Si asignamos 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"


--------------------------------------------------------------------------------


3. Variables locales.
La variable @_, al igual que $_[0], $_[1], ... son locales a la subrutina. Perl permite que podamos definir en las subrutinas nuestras 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 podemos asignarles el valor en la misma línea con:

local($a, $b) = ($_[0], $_[1]);


--------------------------------------------------------------------------------


4. Valores de retorno.
PERL también nos permite retornar valores y lo hace tomando como retorno el último valor escalar que se emplee en la subrutina. El resultado que devuelve una subrutina es la última cosa evaluada.
Así, la subrutina que vimos 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, podemos hacer dos cosas:

sub maximo {
if( $_[0] > $_[1] ) {
$_[0];
}else{
$_[1];
}
}

$mayor = &maximo(37,23); #devuelve 37

o bien:
sub maximo {
if( $_[0] > $_[1] ) {
return $_[0];
}else{
return $_[1];
}
}

$mayor = &maximo(37,23); #devuelve 37

Hacer un programa que incluye una subrutina que devuelve un valor (se puede usar la subrutina anterior) y que el programa llamador la muestre.


Si no utilizamos "return", se devuelve el valor de lo último que evaluáramos:
sub Suma {
$Total = $_[0] + $_[1];
}

# Llamada a la subrutina
print &Suma (2,3);

La suma, el valor devuelto por la subrutina, y la salida del programa será: 5

Si tras la variable $Total tuviesemos otra variable, el valor final retornado sería el valor de esta última variable:
sub Suma {
$Total=$_[0] + $_[1];
$saludo = "Hola Mundo\n";
}

# Llamada a la subrutina
print &Suma (2,3);

La suma dará 5, pero el valor devuelto por la subrutina y la salida del programa será: Hola Mundo


--------------------------------------------------------------------------------

5. Paso de valores por referencia
Hasta ahora hemos visto el pasa de parámetros por valor, es decir, no es posible cambiar los valores globales de los argumentos. Para hacer esto posible es necesario pasar a la función no los valores, sino los nombres de estas variables. Este modo se denomina paso por referencia y se implementa prefijando el nombre de la variable con un arterisco *.
En el momento de la definición de una funcioón cuyos argumentos se pasan por referencia, la asignación de los argumentos a las variables locales se hacen mediante el operador local(*nombre). El ejemplo siguiente ilustra este modo de paso de argumentos describiendo la rutina swap que hace la permuta de los valores de los argumentos.

sub swap {
local(*x, *y) = @_; # asignación local de los argumentos
local($t); # variable local
$t = $x;
$x = $y;
$y = $t;
return @_; # resultado de la función
}
$a = 4; $b = 1;
&swap(*a, *b); # $a =1; $b = 4;
Resulta esencial que la asignación de los argumentos a las variables locales se haga mediante el operador local. Ya que la asignación directa de la variable mediante *nombre=valor modifica las ocurrencias de la variable nombre (globalmente en el script, sino se ha declarado explícitamente como local). Por ejemplo:

sub swap {
(*a, *b) = @_; # asignación de argumentos
local($t);
$t = $a;
$a = $b;
$b = $t;
return @_;
}
$a = 4; $b = 1;
$x = "pi"; $y = 1.414;
&swap(*x, *y); # $x = 1.414; $y = "pi"
print "a=$a, b=$b\n"; # $a = 1.414; $b = "pi"

ESTRUCTURAS DE CONTROL

El desarrollo de un programa viene determinado por el orden en que aparecen las instrucciones. El lenguaje Perl posee controlar un conjunto de instrucciones que permiten controlar el desarrollo de un programa. Estas instrucciones se denominan estructuras de control porque permiten ejecutar un conjunto de instrucciones cuando se verifica una condición o ejecutar iterativamente un bloque de instrucciones mientras una expresión sea válida.

1. La instrucción if.

Es muy parecida a la utilizada en C. La sintaxis de la instrucción if es la siguiente:

if (expresión) {
instrucción o bloque de intrucciones 1;
}
[else {
instrucción o bloque de intrucciones 2;
} ]
El programa evalúa la expresión. Cuando esta expresión resulta verdadera, se ejecuta la instrucción o el bloque de instrucciones 1. Por contra, cuando es falsa de ejecuta la instrucción o bloque de instrucciones 2. Esta última parte es opcional. Para representar una estructura de varios casos se utilizará la sintaxis siguiente:

if (expresión 1) {
instrucción o bloque de instrucciones 1;
}
elsif (expresión 2) {
instrucción o bloque de instrucciones 2;
}
elsif (expresión 3) {
instrucción o bloque de instrucciones 3;
}
else {
intrucción o bloque de instrucciones 4;
}
A continuación veremos un ejemplo sencillo del uso de esta estructura para comprender mejor su funcionamiento:

print "Introduzca un número del cero al dos y pulse Enter:\n";
$var = ;
if ($var == 0) {
print "Esta es la opción 0\n";
}
elsif ($var == 1) {
print "Esta es la opción 1\n";
}
elsif ($var == 2) {
print "Esta es la opción 2\n";
}
else {
print "No existe al opción tecleada\n";
}
2. La instrucción while.

La instrucción while ejecuta iterativamente un bloque de instrucciones mientras una expresión sea válida, evaluando la comprobación en cada iteración. Cuando la prueba es válida, se ejecuta la instrucción o el bloque de instrucciones delimitado por las llaves. La sintaxis de esta instrucción es:

while (expresión) {
instrucción o bloque de instrucciones;
}
He aquí un sencillo ejemplo de manejo de esta estructura:

print "Teclea \"x\" para salir:\n";
$ristra = "";
while ($ristra ne "x") {
$ristra = ;
chop($ristra);
print "Has escrito $ristra\n";
}
print "Salida.\n"
3. La instrucción for.

La instrucción for permite ejecutar iterativamente un conjunto de instrucciones. La sintaxis de la instrucción for es:

for (inicial_exp; test_exp; incremento_exp) {
instrucción o bloque de intrucciones;
}
donde:

inicial_exp es la instrucción que inicializa el bucle. Consiste generalmente en la asignación de un valor a una variable que permite controlar el número de iteraciones.
test_exp es la expresión evaluada en cada iteración. Cuando esta expresión es verdadera, el bloque de instrucciones se ejecuta.
incremento_exp es la expresión que permite la actualización de la variable que controla el número de iteraciones.
A continuación veremos un ejemplo de esta estructura para iniciarnos en su manejo:

print "10 Iteraciones\n";
for ($i=0; $i<10; $i++) {
print "Interación número $i\n";
}
4. La instrucción foreach.

La instrucción foreach es similar a la función del mismo nombre de los Shells de Unix. Asocia iterativamente a una variable cada elemento de la lista. Esta sucesión de valores sirve para parametrizar la ejecución del bloque de instrucción. La sintaxis de la instrucción foreach es:

foreach $variable (@lista) {
instrucción o bloque de instrucciones;
}
Las intrucciones for y foreach son equivalentes. Sin embargo, la utilización de una de estas instrucciones se justifica generalmente por el contexto. El ejemplo siguiente lo ilustra:

@lista = ("elem1", "elem2", "elem3", "elem4");
for ($i = 0; $i<= $#lista; $i++) {
print $lista[$i], "\n";
}
Este ejemplo no utiliza las características de los arrays en Perl. La utilización de la instrucción foreach permitirá recorrer la lista de forma más elegante. El ejemplo siguiente lo ilustra:

@lista = ("elem1", "elem2", "elem3", "elem4");
foreach $elem_actual (@lista) {
print $elem_actual, "\n";
}
5. La instrucción goto.

La instrucción goto label permite cambiar el recorrido lineal de las líneas de código prosiguiendo la ejecución del programa en la línea de etiqueta label. La etiqueta se define colocando al final del identificador dos puntos (:). En el siguiente ejemplo se podrá ver mejor la contrucción del goto.

if ($expr ne $expr_correcta) {
goto error;
}
...
error: print "expresión incorrecta";
La utilización del goto en Perl no es recomendable. Por que le quita al código legibilidad y aumenta la posibilidad de errores.

6. La instrucción last.

La instrucción last interrumpe la ejecución del bucle actual y se ejecuta la instrucción que sigue al bloque. El ejemplo siguiente permite interrumpir el bucle while cuando la variable i toma el valor 3.

$i = 0;
while($i < 6) {
if($i == 3) {
last;
}
$i++;
}
print "el valor de \$i es $i";
Cuando la instrucción tiene como argumento una etiqueta, la ejecución prosigue en la línea indicada por la etiqueta.

7. La instrucción next.

La instrucción next es idéntica a la instrucción continue en C. Interrumpe la ejecución del bloque de instrucción actual y prosigue la ejecución en la iteración siguente. Esta instrucción no interrumpe completamente la ejecución del bucle; la expresión que controla el bucle se evalúa. Si el resultado de la expresión es válido, el bucle se ejecuta de nuevo.

Cuando una instrucción tiene como argumento una etiqueta, la instrucción prosigue en la línea identificada por la etiqueta y no al principio del bloque.

Seguidamente veremos un ejemplo de dicha instrucción:

print "Teclea \"x\" para salir:\n";
print "Si se pulsa la tecla \"s\" no se imprime:\n";
$ristra = "";
while ($ristra ne "x") {
$ristra = ; chop($ristra);
if ($ristra eq "s") {
next;
}
print "Has escrito $ristra\n";
}
print "Salida.\n"
8. La instrucción until.

La instrucción until al igual que la instrucción while permite ejecutar un conjunto de instrucciones un número repetido de veces. Pero al contrario que la la instrucción while, la intrucción until ejecuta dicho bloque de instrucciones mientras no se verifique la comprobación. La sintaxis es:

until (expresión) {
instrucción o bloque de instrucciones;
}
He aquí el ejemplo anterior pero utilizando la instrucción until.

print "Teclea \"x\" para salir:\n";
print "Si se pulsa la tecla \"s\" no se imprime:\n";
$ristra = "";
until ($ristra eq "x") {
$ristra = ; chop($ristra);
if ($ristra eq "s") {
next;
}
print "Has escrito $ristra\n";
}
print "Salida.\n"
9. La instrucción unless.

Esta instrucción es análoga al if, salvo que permite considerar la no verificación de la prueba. Su sintaxis es la siguiente:

unless (expresión) {
instrucción o bloque de intrucciones 1;
}

Para ver mejor el funcionamiento del unless, modificaremos el ejemplo anterior para adaptarlo a dicha instrucción.

print "Teclea \"x\" para salir:\n";
print "Si se pulsa la tecla \"s\" no se imprime:\n";
$ristra = "";
until ($ristra eq "x") {
$ristra = ; chop($ristra);
unless ($ristra eq "s") {
next;
}
print "Has escrito $ristra\n";
}
print "Salida.\n"