Perl

Resumen
Autor: Sandy M. Quintero R.

Introducción

Perl (Practical Extraction and Report Language) es un lenguaje de scripts que corre en la mayoría de los principales sistemas disponibles; Windows, OS/2, Macintosh, UNIX, Linux, BeOS y VMS. De todas estas, definitivamente que UNIX es la principal plataforma de desarrollo de este lenguaje. Perl fué creado por y para la gente UNIX, por lo que no es de extrañar que los desarrollos y la mayoría de las aplicaciones se dan aquí. Pero también, debido al enorme potencial de aplicaciones que tiene, se ha llegando a predecir que éste emergerá como el lenguaje de scripts preferido en la plataforma Windows NT y Microsoft tan ha aceptado este hecho, que está tomando medidas para incluir Perl empotrado en este paquete.
Es un lenguaje interpretado, aunque internamente funciona como un compilador, aunque desarrollado originalmente en un entorno UNIX, actualmente hay versiones para casi todos los sistema operativos.
Hay que tener en cuenta que este lenguaje es el más utilizado para gestionar páginas Web.
 


Datos escalares


 


En Perl existen dos tipos de datos, numeros y strings, pero entre los números estan los enteros y los reales.
Ej: 4,7.5,"hola"

Float : Ej: 1.25,4.25e45,-6.5e24,-1.2E-23

Integer(entero) : Ej: 12,15,-2004,3485
              0377 # 377 octal <=> 255 decimal
              -0xff # ff negativo en hexadecimal <=> -255 decimal

Strings : Ej: "hola",'Como estas'
Para senalar los strings hay dos formas de hacerlo:

Como vimos en estos ejemplos en los double quoted strings, se reconocen cosas como \n,\t,etc. mientras que con single quoted no, pero tiene la ventaja de poder escribirse literalmente lo que se pone entre ellos.
Operadores
Conversión entre números y strings
"123.45juan" # si es operado como número toma el valor 123.45
Ej: $a="3b";
    $b=$a+5; # $b=8
Conversión al reves :
Ej: $a=5;
    "x".$a  # "x5"
Variables Escalares
Una variable escalar es un nombre que mantiene un valor, en Perl las variables deben empezar con '$' .
Estrictamente son nombres para variables escalares:
Nombres de variables escalares
$[a-zA-Z]+[a-zA-Z0-9_]*
$[1-9]+[0-9]* (variables de patern matching)
$\,$/,$_,etc (variables especiales)
Ej:$a,$nombre
Operadores
Ej:$a=17;
   $b=$a+3;
   $b=$b*2;
   $a=4+($a=3); # $b=7,$a=3
   $d=$c=5;
 Interpolación de variables escalares en strings
Si una variable es puesta en un string double quoted (") se interpola el valor de la variable.
Ej:$a="juan";
   $b="hola $a"; # $b="hola juan"
Y si una variable se pone entre single quoted (') no se interpola el valor de la variable.
Ej: $x="hola";
        $y='$x amigo'; # asigna '$x amigo' a $y
En los strings existen tambien algunos modificadores: \U,\u,\L
Ej: $mayjuan="\Ujuan"; # $mayjuan="JUAN"
    $juan="juan"; $mayjuan="\U$juan"; # $mayjuan="JUAN"
    $capjuan="\u$juan"; # $capjuan=Juan
    $pedro="\LPEDRO"; # $pedro="pedro"
    $cappedro="\u\LPEDRO"; #cappedro="Pedro"
    $maypedro="PEDRO"; $cappedro="\u\L$maypedro"; # $cappedro="Pedro"
El valor undef
Que pasa si usamos una variable antes de darle un valor ? , nada fatal, se asigna como cero si es número o "" si es como string.
Ej: $a=3;
        $b=$a+$c; # $b=3
    $x="hola";
    $y=$x.$z; # $y="hola"

Arreglos

Un arreglo es una lista ordenada de datos escalares. Los arreglos pueden tener cualquier número de elementos.
Representación literal
Un arreglo es una lista de valores separados por coma, y dentro de parentesis. Los valores de los elementos pueden ser de distinto tipo.
Ej:   (1,2,3)
      ("juan",4.5)
Sus valores no necesariamente tienen que ser constantes, puede tener variables.
Ej: ($a,17)
    ($b+$c,$d+$e)
El arreglo vacio es representado por () .
Variables
Asi como las variables escalares se representan con un '$' al comienzo, las variables de tipo arreglo empiezan con '@'.
Ej: @a , @hola
Operadores
Asignamiento:
Mediante el operador '=' le podemos dar a una variable arreglo un valor.
Ej:@a=(1,2,3);
   @b=("yo","tu",2);
   @c=@a; # copia el arreglo @a en @c
   @d=($x,$y);
El largo de un arreglo ( ej : @a ) queda guardado en $#a.
Ej:
@a=('b',3,"a");
$d=$a[$#a]; # $d='a'
$c=$#a+5;   # $c=7
Acceso a los elementos
Para enumerar los elementos de un arreglo se empieza desde el 0. El primer elemento del arreglo @a es $a[0], vemos que para accesar un elemento especifico del arreglo ya no se ocupa '@'.
Ej: @a=(7,8,9);
    $b=$a[0]; # asigna 7 a $b
    $a[1]=5; # ahora @a es (7,5,9)
    $a[2]++; # suma uno al tercer valor de @a siendo ahora (7,5,10)
    $c=$a[0]+$a[1];
Hasta ahora solo hemos visto que los indices de los arreglos son constantes, pero tambien pueden ser variables.
Ej:@juan=(7,8,9);
   $a=2;
   $b=$juan[$a];
   $c=$juan[$a-1]; # $c=8
   $d=$a[$#a]; # $d=9
Si uno accesa un elemento del arreglo mas alla del fin del arreglo el valor undef es retornado.
Ej: @a=(1,2,3);
    $b=$a[7]; # $b es 0 o "" , dependiendo del contexto
Asmismo, asignar un valor a un elemento mas alla del fin del arreglo, lo que hace es agrandar el arreglo poniendo undef a los valores intermedios.
Ej: @a=(1,2,3);
    $a[3]="hola"; # @a es ahora (1,2,3,"hola")
    $a[6]="chao"; # @a es ahora (1,2,3,"hola",undef,undef,"chao")
Operaciones sobre arreglos
Push y Pop
Una comun utilización de los arreglos es como stacks, donde los nuevos valores son agregados y borrados por el lado derecho del arreglo. Push() es utilizado para agregar elementos y pop() para sacar.
Ej: @lista=(1,2,3);
    push(@lista,5); # @lista=(1,2,3,5)
    $a=pop(@lista); # $a=5, @a=(1,2,3)
 Shift y Unshift()
Al igual que Pop y Push estos sacan y meten elementos de un arreglo, pero lo hacen por el lado izquierdo.
Ej: @a=(1,2,3);
    unshift(@a,0); # @a=(0,1,2,3);
    $x=shift(@a); # $x=0 , @a=(1,2,3)  
    unshift(@a,5,6,7) # @a=(5,6,7,1,2,3)
El operador reverse
reverse() invierte el orden de los elementos de un arreglo, retornando la lista invertida.
        
Ej: @a=(1,2,3);
    @b=reverse(@a); # @b=(3,2,1)   
    @c=reverse(1,2,3); # lo mismo
Notemos que la lista que se le pasa como parametro permanece inalterable. Si nosotros queremos dejar la lista invertida ahi mismo debemos hacer : @a=reverse(@a)
Sort
Sort toma una lista y la ordena ascendentemente ( segun codigo ASCII ) y retorna la lista ordenada.
Ej: @a=sort("grande","pequeño","chico"); # @a=("chico","pequeño","grande");
    @b=(1,2,4,8,16,32,64);
    @c=sort(@b); # @c=(1,2,16,32,4,64,8)
Como vemos en este ultimo ejemplo sort()ordena por strings, no numericamente.
Chop
chop() trabaja igual que en variables escalares, le saca el ultimo caracter a cada elemento del arreglo.
Ej: @a=("hola","mundo\n","felices dias");
    chop(@a); # @a=("hol","mundo","felices dia")
Operaciones raras
@a=(1,2,3,4,5);
($b,$c,$d)=@a;    # b=1 c=2 d=3

@a=(1,'b',2,'c');
($b,@a)=@a;       # b=1 a=('b',2,'c')

@a=('hola','tu');
@b=(1,2,@a,7,8);  # b=(1,2,'hola','tu',7,8)

@a=(1,2,3,4,5);
@b=@a[1,3];       # b=(2,3,4)

@b=(1,2,3,4,6)[0,1];   # b=(1,2)

@a=(7,8,9);
@b=(1,2,0);
@c=@a[@b];        # c=(8,9,7)
 

Estructuras de control

Al igual que en la mayoria de los lenguajes de programación , en Perl existen estructuras como if, for, while.
if,elseif,else
La estructura de un if es la siguiente :
if ( .... ) {
    ......;
    ......;
}
elsif ( .... ) {
    ......;
    ......;
}
elsif ( .... ) {
    ......;
    ......;
}
else ( .... ) {
    ......;
    ......;
}
Notemos que los elsif y el else van solo si el usuario desea varias preguntas, se podria usar por ejemplo :
if ( $a < 18 )
{
print "Tu eres menor de edad\n";
}
else
{
print "Eres un adulto\n";
}
o :
if ( $a == 0 )
{
$ind++;
print "Incorrecto\n";
}
Digamos tambien que aunque sea una instruccion por if debe ir entre llaves.
While y until
La forma del while es :
while ( condicion ) {
....;
....;
}
Lo que esta entre llaves se ejecuta mientras sea veradera la condicion.
Ej: print "Cuantos años tienes?";
    $a=<STDIN>;
    chop($a);
    while ( $a > 0 )
       {
       print "El año pasado tenias $a años\n";
       $a--;
       }
La forma del until es :
until ( condicion ) {
...;
...;
}
A diferencia del while el until se ejecuta al menos una vez , y se sigue mientras la condicion sea falso , es decir es similar al Repeat/Until de Pascal.
For
La forma general del for es :
for ( exp_inicial; exp_testeo; exp_increm){
...;
...;
}
Ej: for ( $x=0;$x<10;$x++)
       {
       print "Llevas $x puntos\n";
       }
Foreach
El foreach de Perl es muy similar al de C-shell , recibe una lista de valores y asigna cada uno de los valores de la lista a una variable de lectura . La estructura del foreach es :
foreach $a ( @alguna_lista ) {
...;
...;
...;
}
Ej:@a=(3,5,7,9);
   foreach $x (@a) {
      $y=$x*3;
      print "$y\n";
      }
Imprime 9,15,21,27 .
If y unless
Hemos visto que todas las estructuras de control necesitaban de llaves, aunque solo fuera una instruccion; pero esto es incomodo por ejemplo para los if, es por eso que el if se puede usar de otra forma, poniendolo al final de lo que queremos ejecutar:
Ej:
print "Aqui es, Paulina" if ( $user eq 'Paulina' );
Tambien existe el unless, que hace todo lo contrario del if, es decir, ejecuta la accion si no se cumple la condicion del final:
Ej:
$a=45 unless ($a < 12 ); # b valdra 45 si a>=12

 Archivos

En este capitulo no solo veremos archivos, tambien algo de Entrada Standard y del paso de parametros a un programa.
Entrada estandard
Como ya dijimos para leer una linea desde la entrada estandard se debe asignar una variable escalar a <STDIN>
Ej:$a=<STDIN>; # guarda en $a la linea leida 
   chop($a); # le sacamos el enter que tienen todas las lineas por su
                           ingreso
Como procesar toda la entrada estandard ?:
while ( $a=<STDIN> ) 
{
manejo de la linea leida ..... ;
}
El while termina cuando ya no encuentra una linea ingresada desde la entrada estandard.
Otra forma de hacer esto ultimo ( procesar toda la entrada est. ) es asignar <STDIN a una variable de tipo arreglo Ej : @b=<STDIN> ; # en $b[0] guarda la 1a linea, en $b[1] la 2a ....
Lectura de parametros pasados a un programa
Dentro de un programa en Perl los argumentos que se le pasan quedan guardados en el arreglo @ARGV .
Ej: %vi prog1.pl
    #!/usr/local/bin/perl
    print "Tu ingresaste las palabras:\n";
    for($x=0;$x<$#ARGV;$X++)
       {
       print "$ARGV[$x]\n";
       }
    %chmod 755 prog1.pl
    %prog1.pl hola mundo chao
      Tu ingresaste las palabras:
      hola
          mundo
          chao
    %
Procesamiento de archivos
Como en todo lenguaje en Perl se puede trabajar con archivos. Lo primero que se hace es abrirlo y luego leerlo :
Ej: open(FILE,"file1");
    while ( $a=<FILE> ){
    .....;
    }
    close(FILE);
Lo que hicimos en la 1a linea es abrir el archivo de nombre file1 y a ese archivo le asignamos el "file handler" : FILE ( debe ser cualquier nombre pero en mayuscula ) . Luego con el while vamos leyendo linea a linea ( tambien podriamos haberlo hecho como con <STDIN> de asignar una variable de tipo arreglo a <FILE> y habriamos leido el archivo de una pasada ) . Finalmente algo muy importante, es cerrar el archivo .

Por supuesto tambien podemos escribir en un archivo.

Ej:
$file='hola.c';
open (A,">$file");
# Abrimos para solo escritura el archivo hola.c
print A "hola\n";
close(A);
Tambien podemos hacer append a un archivo:
Ej:
@l=('a',"\n",'b',"\n");
open(G,">>/user/jperez/d.txt");
# Abrimos para escritura pero append
print G @l;
close (G);
Veamos dos ejemplos mas interesantes:
Ej:
open (A, "file") || die "No se puede abrir\n";
                      |
                      |
                    vale 1
Un programa que simula 'cp'
$#ARGV != 2 || die "use a.pl origen destino";
open (A,"$ARGV[0]")||die("No se puede leer el origen");
open (B,">$ARGV[1]")||die("No se puede escribir en el destino");
while(  )
   {
   print B || die "No se pudo escribir";
   }
Inclusion de archivos
Al igual que en C, uno puede incluir otro archivo con codigo perl.
Con require incluimos un archivo, el cual no necesariamente tiene que tener un 'main', es decir pueden ser solo subrutinas.
Ejemplo:
#!/usr/local/bin/perl

require "otroarchiv.pl";
# sirve para agregar 
# el codigo que esta en el archivo otroarchiv.pl
Otra forma es con eval, el cual en realidad no sirve en si para incluir archivos, sino que evalua expresiones.
Ejemplo:
$exp='$nombre="juan"; $apellido="perez"; $nombre.=$apellido; print "hola $name\n";';
eval $exp;
# imprimira 'hola juanperez'
Entonces usando eval, podriamos incluir un archivo y que se ejecute:
$arch=`cat archivo`;
$eval $arch;

 Arreglos asociativos

Son igual a los arreglos pero los indice ya no son numeros enteros, pueden ser cualquier cosa. Y asi como los arreglos en su totalidad se denotaban con '@', aca es con '%'.

Ejemplos:

$l{'luis'}='lucho';
$l{'jose'}='pepe';
$a='francisco';
$b='pancho';
$l{$a}=$b;
Lo mismo del ejemplo anterior lo podriamos haber hecho asi:
%l={'luis'=>'lucho','jose'=>'pepe','francisco'=>'pancho'};
foreach $x (%l)
   {
   # Imprimimos el indice y el contenido
   print $x;
   }
%m={'uno'=>'1','dos'=>'2'};
print %m;

uno1dos2
foreach $k ( keys %m)
# keys retorna un arreglo con las llaves del
# arreglo asociativo pasado
   {
   print "llave:$k,contenido:$m{$k}\n";
   }
foreach $k ( sort keys %m)
# sort ordena (keys %m) que es un arreglo que
# contiene las llaves de %m
   {
   print "$k:$m{$k}\n";
   }

dos:2
uno:1
 

Expresiones regulares

En Perl se usa la misma notacion para expresiones regulares de sed y grep :
   .      ->  cualquier caracter
   [e.r]* -> 0 o mas veces e.r.
   [e.r]+ -> 1 0 mas veces e.r.
   ^      -> comienzo de linea
   $      -> fin de linea
   [^e.r] -> no e.r.
Para dar una expresion regular se pasan en '/'. Y para aplicarla a una variable se usa el operador '=~'.
Ejemplos : $a="hola mundo";
           $e="chao";
           $b= ($a =~ /^he/); # $b vale true = 1                
           $c= ( "chao" =~ /ah/ ) ; # $c=0
           $d= ( "$e" =~ /ah/ ); # $d=0
           if ( $a=~ /o$/ )
               { print "Correcto\n"; } # imprime Correcto
El operador '=~' tiene una opcion que lo que hace es como el sed, reemplazar un trozo de texto por otro, esa opcion es la 's' :
El formato es $x =~ s/expant/expnueva/ ;
Ej: $cual="este es un test";
        $cual =~ s/test/prueba/; # $cual ahora es "este es un prueba"
Split() y Join()
Split()
Split() lo que hace es dado un separador, separa un string en un arreglo :
Ej: $linea="mvargas::117:10:Juan";
    @a=split(/:/,$line); # @a=("mvargas","","117","10","Juan")
Join()
Join() hace lo inverso de Split(), dado un arreglo lo junta en un string, separado por un delimitador especificado.
Ej:@campos=(1,2,"hola");
   $salida=join(".",@campos); # $salida="1.2.hola"

 Interfaz con Unix

Al igual que en c-shell o C dentro de un programa en C se puede ejecutar un comando UNIX, o un programa propio en cualquier lenguaje, esto se hace con system(), y de otra forma con '`'.
Ej: #!/usr/local/bin/perl
        print "En el archivo listado dejaremos la lista de archivos\n";
    system("ls -l > listado");
Ej: #!/usr/local/bin/perl
    $num=`wc -c listado`; # en la var. $num deja el numero de caracteres que
                                                        tiene el archivo listado
Nota: Es importante decir que dentro de '`' y system son expandidos los valores de las variables.
Ej:$a="direct1";
   @a=`ls -l -a $a`;
Aqui introducimos un nuevo concepto, resulta que despues de la ejecucion de estas lineas en el arreglo @a quedan guardadas las lineas de salida del comando ls -l -a direct1 .

Existe otra forma de ejecutar comandos Unix, es con el open, el cual tambien tiene las funcionalidades del popen de C, es decir podemos abrir para escribir o leer, un comando:

Ej:
open(FD,"ls |");
@archivos=;
close(FD);
# lo que hizo fue guardar todo lo que retorno el ls
# en el arreglo @archivos, un nombre de archivo en
# cada casilla del arreglo
Tambien podemos escribir en un comando:
Ej:
open(FE,"| sed 's/[,;:.]//g' > salida");
for($x=1;$x<=5;$x++)
  {
  print FE $lin[$x];
  }
close(FE>
# a 5 strings les aplicamos un sed, el cual les elimina
# la puntuacion; el resultado lo deja en el archivo salida

Subrutinas

Al igual que la mayoria de los lenguajes de Programacion, Perl soporta subrutinas, tambien conocidas como procedimientos o funciones.
Con ejemplos, veremos como se construyen.

Ejemplo 1

sub suma {
local($x,$y)=@_;
return($x+$y);
}
# En @_ se reciben los parametros (es por valor)
$f=8;
$c=&suma(4,$f);
# Si yo la hubiera llamado asi: $c=&suma(4,$f,'hola');
# igual funciona
# $c=12
Ejemplo 2
sub duplica() {
$x*=2;
}
$x=8;
&duplicar();
# $x=16, ya que no lo declaramos como 
# local en la subrutina =>
# duplica a x
Ejemplo 3
for($x=0;$x<=n!;$x++)
# este for termina aprox. en n iteraciones,
# ya que se modifica en cada una de ellas
   {
   $y=&duplica($x);
   }
                                              
sub duplica {
$x*=2;
}
Como vimos el paso de parametros es por referencia, pero al igual que en C, los parametros se pueden modificar, via punteros:
Ejemplo 1
&inicializa(*arr);

sub inicializa {
local(*a)=@_;
$a[0]='cero';
$a[1]='cero';
$a[2]='cero';
}
Ejemplo 2
$st='uno:1,dos:2,tres:3';
&crea($st,*a);
# ahora: $a{'uno'}=1, $a{'dos'}=2, $a{'tres'}=3


sub crea {
local($pal,*g)=@_;
local($x,$a,$b);
local(@aux);
@aux=split(/,/,$pal);
for($x=0;$x<=$#aux;$x++)
   {
   ($a,$b)=split(/:/,$aux[$x]);
   $g{$a}=$b;
   }
}
Papers
Infografía

 
Página Principal
Síntesis