2010-11-29 12 views
11

Código¿Por qué no puedo usar el operador de diamante con una matriz en Perl?

$ cat test1 
hello 
i am 
lazer 

nananana 
$ cat 1.pl 
use strict; 
use warnings; 

my @fh; 
open $fh[0], '<', 'test1', or die $!; 

my @res1 = <$fh[0]>; # Way1: why does this not work as expected? 
print @res1."\n"; 

my $fh2 = $fh[0]; 
my @res2 = <$fh2>; # Way2: this works! 
print @res2."\n"; 

Run

$ perl 1.pl 
1 
5 
$ 

No estoy seguro de por qué Way1 no funciona como se esperaba, mientras que Way2 hace. ¿No son esos dos métodos lo mismo? ¿Que está sucediendo aquí?

Respuesta

14

Debido a la naturaleza dual del operador> < (es decir, ¿es glob o readline?), Las reglas son que se comporte como readline, sólo puede tener un bareword o un escalar sencilla dentro de los corchetes. Por lo tanto, deberá asignar el elemento de matriz a un escalar simple (como en su ejemplo), o usar directamente la función de lectura.

+0

impresión 'perl -le' para < < <=>>> '' – tchrist

+0

@tchrist: ¿Algún otro punto aparte de ser un ejemplo divertido de glob? – runrig

+0

No, ese * fue * el punto. :) – tchrist

6

Es porque <$fh[0]> se analiza como glob($fh[0]).

Uso readline lugar:

my @res1 = readline($fh[0]); 
8

Cualquier cosa más compleja que una bareword (interpretado como un identificador de archivo) o un escalar sencilla $var se interpreta como un argumento a la función glob(). Solo las palabras vacías y los escalares simples se tratan como manejadores de archivos para ser iterados por el operador <...>.

Básicamente las reglas son:

<bareword> ~~ readline bareword 
<$scalar> ~~ readline $scalar 
<$array[0]> ~~ glob "$array[0]" 
<anything else> ~~ glob ... 
14

Porque desde perlop:

Si lo que hay dentro de los paréntesis angulares es ni un gestor de archivo ni una variable escalar simple que contiene un gestor de archivo nombre, typeglob o typeglob de referencia, se interpreta como un patrón de nombre de archivo para ser globbed, y se devuelve una lista de nombres de archivo o el siguiente nombre de archivo en la lista, dependiendo del contexto. Esta distinción se determina solo por motivos sintácticos. Eso significa que <$x> es siempre una línea de lectura() desde un identificador indirecto, pero <$hash{key}> es siempre un glob().

Puede deletrear el operador <> como readline para evitar problemas con esta magia.

Cuestiones relacionadas