Septiembre de 1995
Actualizacion: Abril de 1997
Nuetro primer programa sera el ya tipico, que imprime Hola, Mundo! :
#!/usr/local/bin/perl print "Hola, Mundo!\n";La primera linea lo que hace es llamar al compilador de Perl.
Veamos como lo ejecutamos, suponiendo que lo grabamos en un archivo llamado miarchivo.algo
[%] chmod 755 miarchivo.algo [%] miarchivo.algo Hola, Mundo! [%]Veamos un programa ahora en el cual se interactua con el usuario :
#!/usr/local/bin/perl print ("Cual es tu nombre?"); $nombre=<STDIN>; chop($nombre); print "Hola, $nombre!\n";En la segunda linea igual que antes se imprime un mensaje, pero ahora vemos que esta con '()', estos son opcionales. En la siguiente linea se introducen dos nuevos conceptos, primero el de variable ($name),- en el Capitulo II veremos que las variables (escalares) empiezan con '$'-; <STDIN> lo que indica es que se leera una linea desde la entrada estandard. En la cuarta linea la funcion chop() lo que hace es sacarle el ultimo caracter a $name, es decir le quita el Enter (cambio de linea). Y finalmente en la ultima linea lo saludamos, en esta vemos que $name toma el valor que se le ingreso.
Veamos un programa en el cual se eligen opciones :
#!/usr/local/bin/perl print ("Cual es tu nombre?"); $nombre=<STDIN>; chop($nombre); # saca el enter a la linea leida if ( $name eq "Claudio") { print "Hola, Claudio! Como estas!\n"; } else { print "Hola, $nombre\n"; }En la tercera linea vemos el caracter '#' que significa comentario.En la quinta linea se introduce el if, el cual mediante el eq compara dos strings: $name y "Claudio"; hay que hacer notar que el cuerpo del if siempre va entra llaves(aunque sea una linea), al igual que el else, el cual significa que se imprime "Hola, $name\n" si no se cumplio la condicion del if.
Un ultimo programa, en el cual se introducen los ciclos:
#!/usr/local/bin/perl print ("Cual es tu nombre?"); $nombre=<STDIN>; chop($nombre); $palabrasec="llama"; if ( $name eq "Claudio") { print "Hola, Claudio! Como estas!\n"; } else { print "Hola, $nombre\n"; print "Cual es la palabra secreta?"; $palabra=<STDIN>; chop($opcion); while ( $palabra ne $palabrasec ) { print "Error, intentalo de nuevo, cual es la palabra secreta?"; $palabra=En la 16a linea usamos el while, el cual al igual que en otros lenguajes significa que las lineas entre las llaves se repetiran mientras sea verdadera la condicion, la cual en este caso pregunta si $palabra no es igual a $palabrasec; chop($palabra); } }
En Perl existen dos tipos de datos, numeros y strings, pero entre los numeros
estan los enteros y los reales.
Ej: 4,7.5,"hola" Float : Ej: 1.25,4.25e45,-6.5e24,-1.2E-23 Integer : 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:
Ej:'hola' # h,o,l,a 'don\'t' # d,o,n,',t '' # string nulo 'donde\\vas' # d,o,n,d,e,\,v,a,s 'hola\n' # h,o,l,a,\,n 'hola tu' # h,o,l,a,[enter],t,u ( 11 caracteres )
Ej:"hola mundo\n" # hola mundo[enter] "cola\tsprite" # cola[tab]sprite
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.
Ej:2+3 # 5 5.1-2.4 # 2.7 3*12 # 36 2**3 # 8
Ej:"Hola"."mundo" # "Holamundo" "juan"." "."pedro" # "juan pedro"b) Operador de repeticion de strings(x) :
Ej:"juan"x3 # "juanjuanjuan" "pedro"x(4+1) # "pedropedropedropedropedro"c) Operadores de comparacion :
Numeros | Strings |
---|---|
== | eq |
!= | ne |
< | lt |
> | gt |
<= | le |
>= | ge |
Ej: $a="3b"; $b=$a+5; # $b=8Conversion al reves :
Ej: $a=5; "x".$a # "x5"
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
Ej:$a=17; $b=$a+3; $b=$b*2; $a=4+($a=3); # $b=7,$a=3 $d=$c=5;
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 $yEn 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"
Ej: $a=3; $b=$a+$c; # $b=3 $x="hola"; $y=$x.$z; # $y="hola"
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 () .
Ej: @a , @hola
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
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=9Si 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 contextoAsmismo, 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")
Ej: @lista=(1,2,3); push(@lista,5); # @lista=(1,2,3,5) $a=pop(@lista); # $a=5, @a=(1,2,3)
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)
Ej: @a=(1,2,3); @b=reverse(@a); # @b=(3,2,1) @c=reverse(1,2,3); # lo mismoNotemos 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)
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.
Ej: @a=("hola","mundo\n","felices dias"); chop(@a); # @a=("hol","mundo","felices dia")
@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)
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 ( 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 ( exp_inicial; exp_testeo; exp_increm){ ...; ...; }
Ej: for ( $x=0;$x<10;$x++) { print "Llevas $x puntos\n"; }
foreach $a ( @alguna_lista ) { ...; ...; ...; }
Ej:@a=(3,5,7,9); foreach $x (@a) { $y=$x*3; print "$y\n"; } Imprime 9,15,21,27 .
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
Ej:$a=<STDIN>; # guarda en $a la linea leida chop($a); # le sacamos el enter que tienen todas las lineas por su ingresoComo 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.
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 %
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 1Un 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"; }
#!/usr/local/bin/perl require "otroarchiv.pl"; # sirve para agregar # el codigo que esta en el archivo otroarchiv.plOtra forma es con eval, el cual en realidad no sirve en si para incluir archivos, sino que evalua expresiones.
$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;
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
. -> 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 CorrectoEl operador '=~' tiene una opcion que lo que hace es como el sed, reemplazar un trozo de texto por otro, esa opcion es la 's' :
Ej: $cual="este es un test"; $cual =~ s/test/prueba/; # $cual ahora es "este es un prueba"
Ej: $linea="mvargas::117:10:Juan"; @a=split(/:/,$line); # @a=("mvargas","","117","10","Juan")
Ej:@campos=(1,2,"hola"); $salida=join(".",@campos); # $salida="1.2.hola"
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 listadoNota: 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=Tambien podemos escribir en un comando:; 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
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
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; } }