.:: APRENDIENDO PERL: PARTE 1 ::.

Saludos. Empezamos aqui con un artículo (serie de ellos,espero) que tratará de desentrañar los misterios de PERL. Vaya de mano que ni soy gurú, ni me considero hacker ni nada. Pero me gusta la programación y las cosas que se pueden hacer con ella y PERL es un lenguaje que está muy en boga. De este lenguaje sé lo justo pero escribiendo esto me obligo a mirarlo para no meter el cuezo al escribir estas lineas. Espero poder explicar los temas iniciales un poco rápido para poder meter mano a las cosas interesantes por ejemplo, sockets que en PERL son muy sencillos y muy útiles. Lo sé por experiencia.

Sin más dilación, empezamos.

¿Qué necesitamos?

PERL (Practical Extraction and Report Languaje, por si a alguien le interesa) tiene la ventaja de poder ser usado tanto en gnu/Linux como en WIN32. Yo lo tengo en ambos sistemas, en mi Mandrake uso el intérprete que viene de serie, como en la mayoría de los Linux, que también estará instalado por defecto. Para Windows visita www.perl.org y alli te bajas el intérprete que más te guste. Yo tengo el ActivePERL. También tengo una interfaz, Open PERL IDE, para no andar con cmd(s).

Para que un script de PERL se ejecute. Hacemos:

perl programa.pl

(esto en la consola tanto de Linux como de WIN32)

Date cuenta que no tenemos por qué estar en la misma carpeta donde está el programa.En gnu/Linux hay otra forma de ejecutar un programa de PERL. Pon en la primea linea:

#!/usr/local/bin/perl

(que es donde está el binario de perl)

Luego escribiriamos el programa. Dale permiso de ejecución al mismo

chmod 700 programa.pl
ó chmod +x programa.pl

y sencillamente teclea ./programa.pl

Comienzo: Tipos de Variables

ESCALARES: Es la variable básica. Contiene tanto números enteros como flotantes o caracteres. Si sabes algo de C, sabrás que en ese lenguaje debes declarar la variable antes de usarla y decir además de qué tipo es. En Perl, la memoria se asigna dinámicamente segun las va leyendo.

$numero=6, $letra="a", $palabra="ruboslav"

Para que perl reconozca el escalar ha de ir precedido de $

ARRAYS: Es un grupo ordenado de escalares. Los veremos más adelante. Es algo de este estilo:

@fruta=("pera","manzana","naranja")

El array va precedido de una arroba (@).

LISTAS ASOCIATIVAS: Es un tipo especial de array. Va precedido de un %. Lo veremos más adelante.

Basta de charlas. ¡Programemos!

Es la mejor manera de aprender sin duda. Vereis que a medida que avancemos, esto se pone interesante. Empecemos con el ejemplo típico.

print "Hola Coleguitas !!! \n";

Bueno, para el novato en programación diré que \n es retorno de carro y es buena costumbre ponerlo en los print siempre porque sino puede quedar estéticamente feo al ver la salida del programa porque quedan las frases pegadas.También podemos hacer esto:

$frase="Hola colegas";
print $frase;

Pasa lo mismo que con el programa anterior Perl lee la variable escalar $frase y despues la imprime al ver la orden print $frase.

Veamos ahora un ejemplo con arrays y demostraré lo que pasa si no ponemos el simbolo "\n":

Sin \n

@nombres= ("Ana","Luis","Beatriz")
print $nombres[0]
print $nombres[1]
print $nombres[2]

Salida:
AnaLuisBeatriz

 

Con \n

@nombres= ("Ana","Luis","Beatriz");
print $nombres[0],"\n";
print $nombres[1],"\n";
print $nombres[2],"\n";

Salida:
Ana
Luis
Beatriz

Cada uno de los escalares va indexado por un numero siendo el primer miembro del array el cero (¡no el 1!, error típico de la programación), luego el uno, el dos y asi... esperad un poco y veremos cómo hacer para que el ordenador nos haga el código de arriba de una forma automática porque ¿qué pasaría si tuvieramos que sacar 20 nombres? ¿y 1000? no podriamos ponernos a escribir $nombres[0],$nombres[1]...,$nombres[999],sería horrible.
Date cuenta que 1000 elementos están ordenados de 0 a 999 , no de 0 a 1000 (esto serían 1001 elementos).

Vale,¿y las otras variables? ¿las listas asociativas? veamos un ejemplo:

%nombres= ("Ana",10,"Luis",20,"Beatriz",30);
$nombreid=$nombres{"Ana"};
print $nombreid;

La salida es:10

¿Qué hemos hecho aqui? Si os fijais hemos puesto una cadena literal (un nombre) y después un número. Eso quiere decir que el literal va asociado al número que le sigue. En esta ocasion poner algo asi:

%nombres= ("Ana",10,"Luis",20,"Beatriz",30);
print $nombres[0];

No devuelve nada por pantalla. Debemos hacerlo como está arriba que indica que al nombre "Ana" va asociado el numero 10. O sea, asociamos un indice con un escalar.

Bueno, hay más cosas que se podrian contar sobre variables pero de momento con esto vale. Hagamos cosas más interesantes: primero haremos un juego de adivinar numeros y terminaremos con un generador de palabras por fuerza bruta. Mola ¿no?

Programas un poco "serios"

ADIVINAR UN NUMERO

numeros.pl

#este juego es tipico pero nos valdra para varias
#cosas, ver estructuras de control y meter datos
# por el teclado (<STDIN>)

$numero=rand(50)%100;
print "Introduce un numero del 1 al 50 \n";
$teclado=<STDIN>;
while ($teclado<1 || $teclado>50){
print "Introduce un numero del 1 al 50 \n";
$teclado=<STDIN>;
}

while ($teclado!=$numero){
if ($teclado<$numero){
print "El numero que buscas es mayor\n";
}

if ($teclado>$numero){
print "El numero que buscas es menor\n";
}
print $numero,"\n";
print "Introduce un numero del 1 al 50 \n";
$teclado=<STDIN>;
}

print "Acertaste! \n";

La primera linea lo que hace es buscar un numero de 1 a 50 con la funcion rand(nmaximo), ¿qué pinta ahi %100? sencillo, si no lo pusiéramos $numero seria un valor real, o sea, saldrian cosas como 13.3455648 con lo que seria imposible acertar el numero. Damos por supuesto que lo que queremos son números enteros entonces ponemos %100 que se quedará con las 2 primeras cifras, si pusieramos %10 se quedaria sólo con una, etc.

Con $teclado=<STDIN> hacemos que el programa espere una entrada de datos por el teclado (STDIN= STandard INput, o sea,
el teclado) cuando pulsemos return, el programa leerá lo que hayamos puesto.

Si lo que hemos puesto no es un número entre 1 y 50, ejecutará lo que se ve en el bucle while. Un bucle while funciona
asi:

while (condicion/es){ abres bucle
....
codigo a ejecutar
....
} cierras bucle

while es el equivalente en cristiano a "mientras que". O sea, en nuestro ejemplo, mientras que $teclado sea menor que 1 o (||) mayor que 50 ejecutamos lo que hay en el bucle. En este caso pedimos que se introduzca el numero de nuevo. Como veis, hemos introducido dos condiciones: menor que 1 y mayor que 50.

El siguiente while tiene como condicion que se repita si el numero introducido ($teclado) es distinto o no igual (!=) a el numero pensado por el ordenador ($numero). Además nos dirá si el numero que hemos puesto es mayor o menor que $numero con una condicion if que funciona asi:

if (condicion/es){ abres codigo
...
codigo a ejecutar
...
}cierras codigo

if quiere decir si. Si ... (lo que sea) entonces ejecuta lo que hay en corchetes. Este código NO es un bucle a
diferencia del while, sólo lo hará una vez (a no ser que esté dentro de un bucle como es el caso).

Finalmente, si salimos del while sólo puede querer decir que hemos acertado y asi se lo hacemos saber al usuario.

Encontrar palabra por fuerza bruta

brute.pl

@palabra_adivinar=("c","r","o","m","a","d","o"); #la primera palabra que me pasó por la cabeza ;)
@alfabeto=("a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p",
"q","r","s","t","u","v","w","x","y","z");
#En este punto hay 2 formas de hacer el algoritmo de fuerza bruta
#1. Comprobar la palabra caracter a caracter
#2. Comprobar toda la cadena
# Vamos a hacerlo de la primera forma
for ($j=0;$j<7;$j++){
for ($i=0;$i<26;$i++){
if (@alfabeto[$i]==@palabra_adivinar[$j]){
@palabra_encontrada[$j]=@palabra_adivinar[$j];
break;
}
}
}
print "La palabra es: ",@palabra_encontrada;

Bien. Otro programa sencillo para comprender unos conceptos básicos.

Vemos que la palabra a adivinar (@palabra_adivinar) tiene cada uno de sus caracteres separados por comas y metidos entre comilllas con lo cual cada una de sus letras es un indice del array. De momento esto nos vale asi. Hemos hecho idem con el alfabeto que son las letras del abecedario (sólo las minúsculas, si te fijas).

Miremos los comandos for. Son bucles como vimos antes con while pero funcionan de manera distinta. un bucle for tiene entre sus parentesis tres parámetros: La primera es la variable o instrucción que inicializa el bucle,la segunda indica hasta cuando mantenemos activo el bucle y la tercera, lo que varia la instrucción inicial.

O sea, que mientras j sea menor que siete se ejecutará el bucle que hay dentro de sus llaves. siendo j al principio 0 e incrementandose de uno en uno cada vez que se acaba el bucle. ¿Por qué hasta siete? porque son el numero de letras que tiene la palabra "cromado". "¡Pero si ponemos que j sea menor que 7 no contará la ultima letra!" dirá alguno. Cierto es, pero debemos contar también el cero. O sea, que el indice cero de la variable @palabra_adivinar también cuenta y es la primera letra, la c y de 0 a 6 hay 7 letras que son justo las que necesitamos.

El segundo for es el que controla que el programa mira todas las letras que hemos puesto en la variable @alfabeto y comprueba con un if si la letra i del alfabeto encaja con la palabra j de la palabra a adivinar. Si es asi, esa letra pasa a ser parte del array @palabra_encontrada y hacemos break. Break rompe el bucle en el que el programa está en ese momento ¿por qué hacemos eso? sencillo, no hace falta seguir buscando la letra j porque ya la hemos encontrado ¡avancemos un letra más!. Cuando se hallan mirado todas las letras de la palabra a adivinar, en la pantalla imprimimos la palabra encontrada. Si todo va bien debería coincidir con la palabra a adivinar.

Bueno. Este generador de palabras puede ser muy mejorable y es lo que haremos en la siguiente entrega (entre otras cosas). Fijaos que lo hemos hecho comprobando caracter a caracter en vez de la palabra entera ¿por qué? porque es más rápido y si la palabra consta de muchos caracteres nos podemos liar facilmente con los bucles.

La próxima vez haremos que el programa se enfrente al dilema de que los caracteres de la palabra pueda variar (palabras de distinto tamaño) y usaremos diccionarios lo que implica que tendremos que aprender a manejar entradas y salidas de fichero. Ya puestos con el tema de los diccionarios, podríamos hacer un generador de diccionarios. No es complicado, ya vereis.

Ruboslav