@days = (1,2,3,4,5,6,7);
El operador .. toma dos numeros y y devuelve una lista con los enteros entre esos dos números:
DB<1> @b = 4..8 DB<2> p @b # Los elementos son mostrados sin separación 45678 DB<3> p "@b" # Interpolación: los elementos son separados 4 5 6 7 8 DB<4> x @b 0 4 1 5 2 6 3 7 4 8 DB<5> @a = 2.1 .. 4.1 DB<6> x @a 0 2 1 3 2 4
Este operador devuelve una lista vacía cuando .
DB<6> @c = 5..4 DB<7> p @c DB<8> x @c empty array
Los valores individuales de un array se acceden precediendo de un
$
el nombre del array
:
foreach my $i (0..5) { print $days[$i]," es un día laboral/n"; }
El índice del primer elemento es cero.
Si se omite la variable que se usa para indexar en el for, se usará la variable mágica por defecto $_. Así el bucle anterior es equivalente a:
foreach (0..5) { print $days[$_]," es un día laboral/n"; }
Un slice o trozo de un array
resulta de indexar
el array en un subconjunto de índices:
@days # ($days[0], $days[1],... $days[n]) @days[3,4,5] # @days[3..5] @tragedy[3,4,5] = ("Mcburger", "King Leer", "Hamlet, A Pig in the City") @sqrt[1,49,9,16,4] = (1, 7, 3, 4, 2) # índices desordenados @sqr[1..4] = (1, 4, 9, 16) @inverse[@sqr] = (1, 0.25, 0.111, 0.0625); # indexado en un array @list[5..9] = reverse @list[5..9]; # invierte los elementos del 5 al 9 # en list @a[$n, $m] = @a[$m, $n]; # intercambiamos $a[m] y $a[n]
El operador reverse toma los elementos de una lista y devuelve la lista en orden inverso:
DB<1> @a = 1..10 DB<2> @a = reverse @a DB<3> p "@a" 10 9 8 7 6 5 4 3 2 1
En un contexto escalar, cuando reverse
es aplicado a una lista devuelve la cadena
resultante de concatenar los elementos de la lista en orden
inverso:
DB<6> @a = 1..10 DB<7> $b = reverse @a DB<8> p $b 01987654321 DB<9> @a = qw{one two three} DB<10> $x = reverse @a DB<11> p $x eerhtowteno
Si se aplica a una cadena en un contexto escalar produce la recíproca de la cadena:
DB<29> q lhp@nereida:~/public_html/cgi-bin$ perl -wde 0 main::(-e:1): 0 DB<1> $a = "dabale arroz a la zorra el abad" DB<2> p scalar(reverse($a)) daba le arroz al a zorra elabad
Sin embargo, en un contexto de lista la cadena queda sin modificar:
DB<3> p reverse($a) dabale arroz a la zorra el abad
Tenga cuidado si esta trabajando en un entorno que usa UTF-8. En ese caso reverse puede producir un resultado erróneo:
lhp@nereida:~/Lperl/src$ perl -we 'print reverse("dábale arroz a la zorra el abad")."\n"' daba le arroz al a zorra elab##d
Para solucionarlo es necesario usar el
módulo utf8 y poner el fichero de salida en modo
:utf8
:
lhp@nereida:~/Lperl/src$ cat -n reverse.pl 1 #!/usr/local/bin/perl -w 2 use strict; 3 use warnings; 4 use utf8; 5 binmode STDOUT, ':utf8'; 6 my $x = shift || "dábale arroz a la zorra el abad"; 7 print reverse($x)."\n"; # Contexto escalar forzado por el "."Cuando se ejecuta se obtiene:
lhp@nereida:~/Lperl/src$ reverse.pl daba le arroz al a zorra elabád
Una asignación a un elemento que no existe lo crea:
$days[9] = 10;
Los elementos extra $days[6]
, $days[7]
and $days[8]
son asi mismo creados
y se inicializan al valor indefinido undef.
La variable $#days
almacena el índice del último elemento del array
.
En Perl, los índices negativos cuentan desde el final del array
(-1 es el último elemento).
DB<1> @a = 1..10 DB<2> $a[-1] = 1 DB<3> p "@a" 1 2 3 4 5 6 7 8 9 1 DB<4> $a[-20] = 0 Modification of non-creatable array value attempted, subscript -20 at (eval 18) [/usr/share/perl/5.6.1/perl5db.pl:1521] line 2. DB<5> p $#a 9
Si el array completo es accedido en un contexto en el que se espera un
escalar numérico, (scalar context)
el resultado es un escalar conteniendo el número de elementos del array
.
my $i = 0; while ($i < @days) { print $days[$i++],"\n"; }
La función scalar fuerza un contexto escalar:
DB<1> @a = 0..9 DB<2> p "@a\n" 0 1 2 3 4 5 6 7 8 9 DB<3> p "\@a = ",@a,"\n" @a = 0123456789 DB<4> p "\@a = ",scalar @a,"\n" @a = 10
Los arrays
estan muy relacionados, pero no son lo mismo que las listas.
Una lista en Perl es una secuencia de valores separados por comas, normalmente
entre parentesis. Un array es un contenedor para una lista.
Las listas pueden usarse para extraer valores de los arrays
. Por ejemplo:
($d1, $d2) = @days;
Se puede asignar listas de valores a listas de variables:
($a, $b) = ($b, $a);que intercambia los valores de
$a
y $b
.
En una Asignación a una lista, si hay mas variables en la lista que
elementos en la parte derecha , las variables
extra quedan indefinidas (undef
). Si por el contrario hay menos variables
que elementos en la parte derecha, los elementos extra son ignorados.
Veamos un ejemplo:
lhp@nereida:~/Lperl/src$ perl -wde 0 main::(-e:1): 0 DB<1> @a = 1..3 DB<2> @b = 1..5 DB<3> ($a,$b) = @a DB<4> x ($a,$b) 0 1 1 2 DB<5> ($c,$b,$a) = (2,7) DB<6> x ($c,$b,$a) 0 2 1 7 2 undef DB<7> ($c,$b,$a) = (2,7,9,12,@b) DB<8> x ($c,$b,$a) 0 2 1 7 2 9Sin embargo si la parte izquierda es un array, la variable se hace igual a la lista que esta en la parte derecha:
DB<9> @b = reverse @a DB<10> x @b 0 3 1 2 2 1
Una abreviación muy cómoda para crear listas de cadenas la proporciona el operador qw. Una cadena formada por palabras separadas por espacios en blanco dentro de qw se descompone en la lista de sus palabras.
@a = qw(uno dos tres); # @a == ("uno","dos", "tres")Observa que no se ponen comas entre las palabras. Si por error escribieras:
@a = qw(uno, dos, tres); # @a == ("uno,","dos,", "tres")obtendrías comas extra en los elementos de la lista.
Otro ejemplo:
@week = qw(monday tuesday wednesday thursday friday saturday sunday);
Los escalares no inicializados tienen el valor undef. Sin embargo, las variables array no inicializadas tienen como valor la lista vacía (). Si se asigna undef a una variable de tipo array lo que se obtiene es una lista cuyo único elemento es undef:
@a = undef; # Equivalente a @a = ( undef ); if (@a) { ... } # Por tanto TRUEEl modo mas simple de evitar este tipo de problemas cuando se quiere limpiar una variable de tipo array es asignar explícitamente la lista vacía ():
@a = (); if (@a) { ...}; # scalar(@a) == 0 es FALSETambién se puede usar el operador undef:
undef @a; if (defined(@a)) { ... }; # FALSE
Es posible asignar undef a los elementos de un array:
$a[3] = undef;O bien usando la lista vacía, como se hace en la siguiente sesión con el depurador:
DB<1> @a = 0..9 DB<2> @a[1,5,7] = () DB<3> p "@a" 0 2 3 4 6 8 9 DB<4> p $#a 9 DB<5> p scalar(@a) 10 DB<6> $" = "," # separador de output de arrays DB<7> p "@a" 0,,2,3,4,,6,,8,9 DB<8> @a[1..7] = () DB<9> p "@a" 0,,,,,,,,8,9
$"
. Esta variable contiene un espacio por defecto.
DB<1> @a = 0..9 DB<2> print "@a 10\n" 0 1 2 3 4 5 6 7 8 9 10 DB<3> $email = "casiano@ull.es" DB<4> print $email casiano.es DB<5> $email = 'casiano@ull.es' DB<6> print $email casiano@ull.es DB<7> $email = "casiano\@ull.es" DB<8> print $email casiano@ull.es
Un único elemento de un array es reemplazado por su valor. La expresión que aparece como índice es evaluada como una expresión normal, como si estuviera fuera de una cadena:
DB<1> @a = 0..9 DB<2> $i = 2 DB<3> $x = "$a[1]" DB<4> p $x 1 DB<5> $x = "$a[$i-1]" DB<6> p $x 1 DB<7> $i = "2*4" DB<8> $x = "$a[$i-1]" DB<9> p $x 1
p $x
en el último ejemplo?
Dado la siguiente sesión con el depurador
nereida:~/perl/src> perl -de 0 main::(-e:1): 0 DB<1> @a = 1..5 DB<2> ($a[0], $a[1]) = undef DB<3> p "@a"¿Cuál es la salida de la impresión que aparece al final de la secuencia de comandos?. ¿Se produce alguna dvertencia? ¿Que ocurre si se cambia la última línea por esta otra?
DB<3> no warnings; $" = ', '; print "@a"
lhp@nereida:~/Lperl/src$ cat -n foreach1.pl 1 #!/usr/bin/perl -w 2 use strict; 3 4 my @list = 1..10; 5 foreach my $n (@list) { 6 $n *= 2; 7 } 8 print "@list\n";su ejecución produce la siguiente salida:
lhp@nereida:~/Lperl/src$ foreach1.pl 2 4 6 8 10 12 14 16 18 20