Este capiítulo cubre todo los básicos de Perl.
La intención es mostrar como se hace Perl lo que se puede hacer en cualquier otro lenguaje de programación.
Como correr un programa de Perl desde la linea de comando:
Abrir una ventana de shell (xterm).
Escribir
perl -e 'print "Hello, world!\n";'
That's it!
Tarea: Correr desde la linea de comando un programa que escribe tu nombre 3 veces.
Editores:
emacs:
Emacs es uno de los editores de texto más poderosos.
Se puede personalizar practicamente cualquier aspecto del editor, y hay plugins para todo tipo de programación.
Esto texto, por ejemplo, está hecho con un plugin de HTML/CSS.
Los mismos plugins se puede personalizar, como son archivos de texto.
Emacs ya incluye modos especiales para Perl, cperl-mode y perl-mode.
Se carga perl-mode automáticamente al abrir un archivo con la extensión .pl o .cgi
Las últimas versiones de Emacs ya vienen con una barra de edición para el principiante, aunque la filosofía de Emacs es usar el teclado cuando esto es posible (mucho más rápido que usar el mouse).
vi:
Si ya estas acostumbrado, probablemente tu favorito.
Si no, no lo intentes. ;-)
IDE (Integrated Development Environment):
Hay IDEs para Perl, pero para la mayoría de tareas el desarrollo es más lento con un IDE que con un editor de texto, así no se recomienda usar IDEs.
a tu gusto:
Muchas veces el poder no está tanto en el editor como en la costumbre del programador.
El favorito mio es Emacs, el tuyo puede ser otro.
Si ya tienes un editor de texto como tu favorito, probablemente es la mejor opción para ti.
Mejor todavía si tiene alguna funcionalidad especial para Perl ;-)
Tarea: Investigar si tu editor de texto tiene un plugin para Perl.
Como correr un programa de Perl guardado en un archivo de texto:
Se puede guardar el programa arriba en un archivo de texto helloworld.pl de una sola linea: print "Hello, world!\n";
y se ejecuta con
perl helloworld.pl
Siempre es recomendable correr un programa de Perl con la opción -w, warnings:
perl -w helloworld.pl
que despliega advertencias de todo tipo.
Siempre es recomendable poner como primera linea el full path a Perl
(requisito para scripts CGI): #!/usr/bin/perl
Puede ser que el full path en tu sistema es otro, por ejemplo #!/usr/local/bin/perl
Prueba con
which perl
desde la linea de comando para ver el full path de tu sistema.
Se puede agregar opciones en la primera linea también: #!/usr/bin/perl -w
en la primera linea significa que el script siempre usa warnings.
Siempre es recomendable poner como segunda linea: use strict;
Como dice, exige programación más estricta, exige declaración de variables, etc.
Es una gran ayuda para evitar bugs en programas.
Siempre es recomendable poner un comentario, una descripción breve del programa: # This program says hello to all the world.
Todo lo que sigue después del signo # se toma un comentario, hasta el final de la linea.
Siempre es recomendable hacer un script ejecutable
(requisito para scripts CGI):
chmod 755 helloworld.pl
Así se puede ejecutar el programa solo con
./hello.pl
Si guardas el programa en un directorio que está incluido en el environment variable PATH, normalmente /bin, /usr/bin, /usr/local/bin y $HOME/bin es suficiente escribir
helloworld.pl
Resumen:
Siempre iniciar un programa como este ejemplo: helloworld2.pl
#!/usr/bin/perl -w
use strict;
#
# This program says hello to all the world.
#
print "Hello, world!\n";
Siempre hacer el programa ejecutable:
chmod 755 helloworld2.pl
Tarea: Hacer un programa hellohola.pl que despliega "Hello" en inglés y en español.
Correrlo como
Para interpolar ("parsear") el valor de un Scalar se usa comilla doble:
# despliega: Esto vale 100 dolares
my $sum = 100;
print "Esto vale $sum dolares\n";
Para evitar interpolación se usa comilla simple:
# despliega: Esto vale $sum dolares\n
my $sum = 100;
print 'Esto vale $sum dolares\n';
Tarea: Hacer un programa que declara nombre, apellido y edad como Scalars, luego despliegarlos en una sola linea.
Arrays:
Arrays son arreglos de Scalars, comienzan con una @:
Ejemplos:
# Nota: El arreglo comienza con una @,
# como es un Array
# pero cada elemento en el arreglo comienza con una $,
# como es un Scalar.
my @carros;
$carros[0] = 'Honda';
$carros[1] = 'Ferrari';
$carros[2] = 'Volvo';
$carros[3] = 'Chrysler';
$carros[4] = 'Smart';
# Usando 'for' para desplegar:
for (my $i = 0; $i< = 4; $i++) {
print $carros[$i], "\n";
}
# Usando 'foreach':
foreach my $carro (@carros) {
print $carro, "\n";
}
Se puede asignar el mismo Array como:
# The lazy way
my @carros = ('Honda', 'Ferrari', 'Volvo', 'Chrysler', 'Smart');
El el último ejemplo arriba se utiliza un LIST para asignar a un Array sus valores.
Un LIST simplemente es una lista de uno o más Scalars, separados por coma.
La función push, (escribir perldoc -f push desde la linea de comando), toma una lista como su segundo argumento: push ARRAY,LIST
Quiere decir que se puede agregar varios elementos a la vez a un arreglo:
# La lista sigue...
push @carros, ('Datsun', 'Mercedez', 'Porsche');
Un Array entre parentesis actúa como una lista.
Una función o subrutina que devuelve un Scalar o un Array también actúa como una lista.
my @vehiculos = (@carros, @bicicletas, &MiMoto());
Un Array también puede asignar valores a una lista:
# Se supone que @nombres lleva los 4 nombres
($mama, $papa, $hijo, $hija) = @nombres;
# Truco para intercambiar nombre de $papa e $hijo,
# sin usar un variable temporal:
($papa, $hijo) = ($hijo, $papa);
El tamaño de un array:
# Usar un arreglo con un scalar (devuelve el tamaño del arreglo)
my $count = scalar(@carros);
# Igual que el ejemplo arriba
my $count = @carros;
Tarea: Hacer un programa que asigna 5 números a un Array, y que despliega el quinto elemento del Array.
Hashes:
Hashes son como arreglos de Scalars usando un string para sus índices, llamados keys, en vez de un número, comienzan con una %.
Hashes usan {} como encerrar cada key, no como los [] para los índices de Arrays.
Un hash no se puede interpretar como una lista, así no se puede agregar un hash a un array usando la función push, por ejemplo.
Cada elemento en un hash consiste de un key y un value, o sea un key/value pair.
Para accesar cada elemento en un hash se usa la función keys.
Como dice perldoc -f keys, la función devuelve una lista de los índices del hash.
Ejemplos:
# Nota: El hash comienza con una %,
# como es un Hash
# pero cada elemento en el hash comienza con una $,
# como es un Scalar.
my %carros;
$carros{'lunes'} = 'Honda';
$carros{'martes'} = 'Ferrari';
$carros{'miercoles'} = 'Volvo';
$carros{'jueves'} = 'Chrysler';
$carros{'viernes'} = 'Smart';
# Desplegar todos los keys en una sola linea
print keys %carros, "\n";
# No se puede usar 'for' con hashes, solo 'foreach':
foreach my $dia (keys %carros) {
my $carro = $carros{$dia};
print "El dia $dia uso el carro $carro.\n";
}
Como se ve en el ejemplo arriba, un hash no devuelve los valores ordenados.
Para ordenar un hash se puede usar la función sort:
# Ordenar por key (dia)
foreach my $dia (sort(keys %carros)) {
print $dia, '=', $carros{$dia}, "\n";
}
# Ordenar por value (carro) es un poco más complicado:
foreach my $dia (sort { $carros{$a} cmp $carros{$b} } keys %carros) {
print "$carros{$dia} me parece bien el $dia.\n";
}
Una asignación de hash más legible:
# NOTA: La última linea también permite finalizar con coma,
# para poder agregar mas keys después, sin modificar la última linea.
my %carros = (
lunes => 'Honda',
martes => 'Ferrari',
miercoles => 'Volvo',
jueves => 'Chrysler',
viernes => 'Smart',
);
Tarea: Hacer un programa que asigna 5 números a un Hash con keys a,b,c,d,e.
Que despliegue el elemento 'c' del Hash.
Que despliegue el tamaño del Hash.
Subroutines and functions:
Subrutinas son como funciones, la única distinción entre una subrutina (creada por el programador) y una función (definida en Perl) es que la subrutina comienzan con una &, (pero el & es opcional).
Así se tratan igual en un programa, lo que cuenta es lo que una función/subrutina devuelve.
Si devuelve un Scalar, se trata como un Scalar, si devuelve un Array, se trata como Array, etc.
Una subrutina comienza con sub, el valor se devuelve con return.
Los argumentos están en el Array @_.
Se puede obtener los argumentos uno por uno con shift
Ejemplos:
# Subrutina que devuelve un Scalar
sub returnScalar {
my $first_argument = shift;
return "El argumento es: $first_argument";
}
# Subrutina que devuelve un Array
sub returnArray {
my $array_size = shift;
my @array = ();
for (my $i = 0; $i <= $array_size - 1; $i++) {
$array[$i] = $i.$i;
}
return @array;
}
# Subrutina que devuelve un Hash
sub returnHash {
my @keys = @_;
my %hash = ();
foreach my $key (@keys) {
$hash{$key} = $key.$key;
}
return %hash;
}
# Usar las subrutinas
print "Scalar:\n";
print returnScalar('test 1'), "\n", returnScalar('test 2'), "\n";
print "Array:\n";
my @test_array = returnArray(5);
for (my $i = 0; $i <= @test_array - 1; $i++) {
print "$test_array[$i]\n";
}
print "Hash:\n";
my %test_hash = returnHash('mama', 'papa', 'hijo', 'hija');
foreach my $key (keys %test_hash) {
print "$test_hash{$key}\n";
}
Cuando se corre un programa desde la linea de comando, se puede interpretar como una subrutina.
La única diferencia es que se usa el array @ARGV en vez de @_.
Tarea: Hacer un subrutina que despliega el tercer elemento de un arreglo.
References en Perl son como pointers en C - apuntan a una dirección donde se almacena el valor del variable.
Se puede hacer una referencia a un Scalar, Array, Hash o Sub, pero la referencia en si siempre se trata como un Scalar, así comienzan con una $.
Para crear una referencia a un variable se usa \, para obtener el variable se usa el prefijo correspondiente.
Ejemplos:
# Crear referencias
my $scalar = 'hola';
my $scalar_ref = \$scalar;
print "Scalar: $$scalar_ref\n";
my @arr = (1, 2, 3);
my $arr_ref = \@arr;
print "Array: @$arr_ref\n";
my %hash = (
nombre => 'Carlos',
apellido => 'Sanchez',
edad => 25,
);
my $hash_ref = \%hash;
print "Hash size: ", scalar(keys %$hash_ref), "\n";
Una subrutina que devuelve un array o un hash grande es ineficiente.
Es más eficiente devolver una referencia al array o hash:
print "Array size (inefficient): ", scalar(&un_arreglo_grande()), "\n";
print "Array size (efficient): ", scalar(@{&ref_a_un_arreglo_grande}), "\n";
sub un_arreglo_grande {
my @arr = (1..1000);
return @arr;
}
sub ref_a_un_arreglo_grande {
my @arr = (1..1000);
return \@arr;
}
Para crear una referencia a una lista, se puede usar [] en la lista en vez de ().
Esto es una manera para crear multi-dimension arrays:
# Referencia a una lista
my $ref_a_arreglo = [ 'a0', 'a1', 'a2' ];
print "$ref_a_arreglo->[1]\n";
# Referencia a una lista de listas (o sea, un multi-dimension arrays)
my $ref_a_multi_arreglo = [
[ 'a0', 'a1', 'a2' ],
[ 'b0', 'b1', 'b2', 'b3' ],
[ 'c0', 'c1', 'c2' ],
];
# Desplegar elemento (1,3) = 'b3'
print "$ref_a_multi_arreglo->[1][3]\n";
Tarea: Crear una referencia a una lista, desplegar todos los elementos.
El valor falso o verdadero siempre se evalua como un Scalar.
Las 4 reglas de true/false en Perl:
Una cadena es verdad, menos las dos cadenas "" y "0".
Un número es verdad, menos el número 0.
Una referencia siempre es verdad
Un valor no definido siempre es falso
Se puede pensar solo en cadenas, así el número 0 se convierte en la cadena "0", que de todo modos evalua a falso.
Ejemplos:
0 # Como la cadena "0" - falso
1 # Como la cadena "1" - verdad
10 - 10 # Igual a 0, como la cadena "0" - falso
0.00 # Como número evalua a 0, como la cadena "0" - falso
"0.00" # No igual a la cadena "0" - verdad
"0.00" + 0 # Evalua a 0 - falso
"" # NULL - falso
\$ref # Una referencia contiene la dirección adonde apunta,
# siempre <> 0 - verdad
undef() # Devuelve un valor no definido - falso
En UNIX es común que un comando devuelve 0 si fue exitoso, y <> 0 si falló el comando:
# Obtener el nombre de archivo desde la linea de comando.
# Salirse si '$filename = $ARGV[0]' evalua a "undefined", o sea falso
my $filename = $ARGV[0] or die "Por favor ingresar nombre de archivo.\n";
# Un comando UNIX
my $command = 'ls -la '. $filename;
# No desplegar mensajes de error, solo captar el codigo.
my $output = `$command > /dev/null 2>&1`;
# Obtener el codigo de error
my $error_code = $?;
# Salirse si '$error_code = 0' evalua a falso,
# o sea salirse si $error_code <> 0
$error_code == 0 or die "Error $error_code\n";
# Como no hubo errores, ahora desplegar el output
$output = `$command`;
print $output;
Lógicos: || && ! and or not
Los operadores de C && || !son iguales de los más legibles and, or, not.
La única diferencia es "precedence", más bajo para and, or, not.
Para asegurarse que evalue con "precedence" la operación lógica, hay que poner la expresión entre parentesis, especialmente con and, or, not:
En la mayoría de los casos no hay diferencias:
$a = '0';
$b = $a || 2; # Como $a evalua a "0" (falso),
# se evalua la parte derecha de ||, $b = 2
$b = ($a || 2); # Igual que el ejemplo anterior (parentesises opcionales)
$b = ($a or 2); # Igual que el ejemplo anterior (parentesises requeridos)
$a = '3';
$b = $a || 2; # Como $a evalua a "3" (verdad),
# se ignora la parte derecha de ||, $b = 3
$b = ($a || 2); # Igual que el ejemplo anterior
$b = ($a or 2); # Igual que el ejemplo anterior
$a = '0';
$b = $a && 2; # Como $a evalua a "0" (falso),
# se ignora la parte derecha de &&, $b = 0
$b = ($a && 2); # Igual que el ejemplo anterior
$b = ($a and 2); # Igual que el ejemplo anterior
$a = '3';
$b = $a && 2; # Como $a evalua a "3" (verdad),
# se evalua la parte derecha de ||, $b = 2
$b = ($a && 2); # Igual que el ejemplo anterior
$b = ($a and 2); # Igual que el ejemplo anterior
Increase & decrease: ++ --
Se lee la expresión $b = $a++ como "primero $b = $a, luego se incrementa $a".
Ejemplos:
Comparación:== != < > <= >= eq ne lt gt le ge
Los operadores == != < > <= >= se aplican a números.
Los operadores eq ne lt gt le ge se aplican a cadenas.
Normalmente sólo se usan eq ne para cadenas.
Ejemplos:
$a = 1;
$b = 3;
if ($a < $b) ... # Verdad
if ($a <= $b) ... # Verdad
if ($a != $b) ... # Verdad
if ($a == $b) ... # Falso
$a = 'hola';
$b = 'que tal';
if ($a eq $b) ... # Falso
if ($a ne $b) ... # Verdad
Tarea: Hacer un programa con 10 lineas de if, con condiciones distintas.
Se puede evitar el uso de unless (negación de if), y until (negación de while), la función es idéntica:
unless ($edad >= 18) ...
# igual que lo anterior
if ($edad < 18) ...
until ($boletos_vendidos >= 1000) ...
# igual que lo anterior
while ($boletos_vendidos < 1000) ...
Perl es flexible, igual que un idioma natural se puede agregar el if al final:
print "Hoy es lunes\n" if ($weekday eq 'lunes');
Loops:for, foreach, next, last
El uso de foreach es mucho más común que for.
El foreach es bueno para procesar todos los elementos de un array o un hash (ver sección de variables arriba).
El for se usa para obtener un índice específico:
for (my $i = 0; $i <= @array; $i++) {
if ($i == 123) {print "This is index 123\n";}
}
El next y last se usan como condiciones dentro de un loop for o foreach:
for (my $i = 0; $i <= @array; $i++) {
# Ignore index less then 100 and index 5000
if ($i < 100 or $i == 5000) {next;}
# Exit loop when found a special case
if ($array[$i] == '999') {print "Found at $i!\n"; last;}
}
Como hacer un select/case en Perl:
Perl no cuenta con un comando tipo select o switch.
Una forma (entre muchas) de realizar un select/case:
for ($carro) {
/Mercedez/ and do { print "Agradable, pero caro!\n"; last; } ;
/Datsun/ and do { print "Un poco viejo...\n"; last; } ;
/Golf/ and do { print "No tan mal...\n"; last; } ;
print "El carro $carro no conozco.\n";
}
Tarea: Hacer un programa con un loop de 1 a 10, un select que despliega algo especial para los casos 2 y 7.
Muchas veces es practico tener el archivo en un arreglo, una linea por elemento:
open(FH, '</var/log/messages');
my @contents = <FH>; # Todo el contenido al arreglo
close(FH);
foreach my $line (@contents) {
print "$line";
}
Para escribir a un archivo:
open(FH, '>/tmp/test');
print FH "Esto escribo al archivo /tmp/test\n";
close(FH);
Para agregar al final de un archivo:
open(FH, '>>/tmp/test');
print FH "Esto agrego al final del archivo /tmp/test\n";
close(FH);
File test operators:
Perl usa la misma forma como el comando UNIX test para hacer pruebas de archivos.
Leer en perldoc perlfunc, o bien el manpage de test, man test para ver el listado de todos los file operators.
Ejemplo:
if (-f $filename) ... # Verdad si el archivo existe y es u archivo regular
Borrar un archivo:
unlink $filename;
Tarea: Hacer un programa que escribe "Hello, World!" 100 veces al archivo "junk.txt", luego leer el contenido a un arreglo, desplegar cada linea con número de índice, luego borrar el archivo.
Documentación:
La documentación de Perl es bien completa, se instala junto con Perl, usando perldoc desde la linea de comando.
La jerarquia se ve con perldoc perl.
Los documentos más útiles:
perldata Perl data structures
perlsyn Perl syntax
perlop Perl operators and precedence
perlre Perl regular expressions
perlfunc Perl builtin functions
Desde la linea de comando se accesan con perldoc perlfunc, por ejemplo.
Para ver info de una función en especial, por ejemplo push se escribe perldoc -f push.
Para listar todos los módulos (extras, desde CPAN) instalados: perldoc perllocal.
Tanto para módulos estandar, como CGI como para módulos de CPAN, como DBD::MySQL se usa perldoc CGI o perldoc DBD::MySQL.
Tip: Se puede buscar en las páginas con la tecla / y buscar próximo con la tecla n.
Definición de estilo de programación:
Comentarios:
Deben abundar en cualquier programa, el error principal es no poner comentarios.
Como primer caracter se usa #, un espacio, luego el texto.
El comentario debe ser indentado tantos caracteres como el código.
Aunque se puede agregar un comentario al final de una linea de código, se debe evitarlo.
En ejemplos como en este documento se acepta, pero en una aplicación se debe tener los comentarios en una linea aparte.
Los comentarios pueden usar inglés o español, pero sin mezclar idiomas.
Indenting:
Cada nivel debe usar 2 (cperl-mode) o 4 (perl-mode) espacios de indenting, debe ser coherente en todos los documentos.
La lleve de apertura { debe estar en la misma linea como un if o un foreach.
La lleve de cierre } debe estar sólo en una linea.
Un posible else { debe estar en la siguiente linea.
Nombres de variables:
Todos los nombres deben estar en el mismo idioma, que sea inglés o español.
Esto viene integrado con el diseño de la base de datos, y de módulos.
Es recomendable usar _ como separador, es más legible llamar un variable $esto_es_un_variable que $estoEsUnVariable.
Como Perl ve subrutinas como variables, este estilo también aplica a subrutinas.
Archivos deben nombrarse con - por estandar de internet: esto-es-un-archivo.txt.
Módulos normalmente usan mayúscula para la primera letra, y solo mayúsculas si es una abreviatura.
Para nombrar un módulo del proyecto Servicios Portuarios, sería conveniente usar: SP::Contenedor SP::Menu SP::Reporte
etc.
Los métodos de módulos son variables, por eso aplica el nombramiento arriba.
Ejemplo de un método del módulo DBI (usa _ entre fetchrow y array: @row_ary = $sth->fetchrow_array;