2016-01-15 18 views
10

Questo script:

#!/usr/bin/perl 
use strict; 
use warnings; 

my ${fh}; 

open($fh, '<', "some_file.txt") or die "fail\n"; 

while(my $line = <${fh}>) { 
    print $line; 
} 
close $fh; 

uscite:

GLOB(0x5bcc2a0) 

Perché questo è l'uscita?

Se cambio a, verrà stampato some_file.txt riga per riga come previsto. Ho pensato che le parentesi potevano essere usate per delimitare i nomi delle variabili e che sarebbe lo stesso di my $var.

Esistono altri scenari in cui l'aggiunta di {} a un nome di variabile causa problemi?

Ho provato su Perl 5.8.8 su Red Hat e Cygwin Perl 5.14.

+0

Ci sono molti scenari in cui l'aggiunta di '{}' cambia l'analisi, ad es. '" $ foobar "' vs. '" $ {foo} bar "', '" $ foo :: bar "' vs. '" $ {foo} :: bar "', '" $ foo's bar "' vs. '" La barra di $ {foo} "', '" $ pippo [0] "' vs. '" $ {pippo} [0] "'. Ma immagino che tu stia chiedendo delle situazioni oltre all'interpolazione delle stringhe? – ThisSuitIsBlackNot

+0

@ThisSuitIsBlackNon hai indovinato. Ottima risposta anche! – chilemagic

risposta

18

Dalla sezione sulla <> in perlop:

Se le parentesi angolari contengono una variabile scalare semplice (per esempio, $foo), allora quella variabile contiene il nome del filehandle di input da, o il suo typeglob, o un riferimento allo stesso. Ad esempio:

$fh = \*STDIN; 
$line = <$fh>; 

Se ciò che è all'interno delle parentesi angolari è né un filehandle nè una semplice variabile scalare contenente un nome filehandle, typeglob, o riferimento typeglob, viene interpretato come schema di nome da globbed, e di un lista di nomi di file o il nome file successivo nell'elenco viene restituito, a seconda del contesto. Questa distinzione è determinata solo da motivi sintattici. Ciò significa che <$x> è sempre un readline() da un handle indiretto, ma <$hash{key}> è sempre un glob(). Questo perché $x è una semplice variabile scalare, ma non lo è $hash{key} - è un elemento di hash. Anche <$x > (notare lo spazio extra) viene considerato come glob("$x "), non readline($x).

Si può vedere questo con B::Concise:

$ perl -MO=Concise -e'<$fh>' 
5 <@> leave[1 ref] vKP/REFC ->(end) 
1  <0> enter ->2 
2  <;> nextstate(main 1 -e:1) v:{ ->3 
4  <1> readline[t1] vK*/1 ->5 
-  <1> ex-rv2sv sK/1 ->4 
3   <$> gvsv(*fh) s ->4 
-e syntax OK 

$ perl -MO=Concise -e'<${fh}>' 
6 <@> leave[1 ref] vKP/REFC ->(end) 
1  <0> enter ->2 
2  <;> nextstate(main 70 -e:1) v:{ ->3 
5  <@> glob[t1] vK/1 ->6 
-  <0> ex-pushmark s ->3 
-  <1> ex-rv2sv sK/1 ->4 
3   <$> gvsv(*fh) s ->4 
4  <$> gv(*_GEN_0) s ->5 
-e syntax OK 
11
  • <> significa readline(ARGV)
  • <IDENTIFIER> significa readline(IDENTIFIER)
  • <$IDENTIFIER> significa readline($IDENTIFIER)
  • <...> (altro) mi ans glob(qq<...>)

Quindi,

  • <$fh> significa readline($fh)
  • <${fh}> mezzi glob(qq<${fh}>), che è la stessa come glob("$fh").

glob viene utilizzato per generare un numero di stringhe o nomi di file da un motivo.

In questo caso, la stringificazione dell'handle del file è GLOB(0x5bcc2a0). Questo viene passato a glob, ma nessuno di questi personaggi ha un significato speciale per glob, quindi glob restituisce semplicemente quella stringa.

+0

Quindi in pratica '<>' è definito a livello di carattere assoluto ... wow, lavoro di flunk CS! – Kaz

+4

@ Kaz, dove l'hai preso? Il mio post lo ha definito in termini di token. Anche se usasse una sotto-lingua (come 'm //', 'tr ///', 'sprintf' e' glob' do), non vedo perché questo metta a nodo le tue mutandine. – ikegami

+0

Nell'altra risposta si nota (citato dalla documentazione) che anche "<$x >" è completamente diverso da "<$x>". – Kaz

Problemi correlati