2011-02-08 10 views
6

Sto tentando di aprire il file ricevuto come argomento.Perl: file di apertura

Quando archiviano l'argomento nella variabile globale aperto funziona correttamente.

Ma

Se uso dare renderlo come il mio aperta non riesce a aperta il file.

Qual è il motivo.

#use strict; 
use warnings; 

#my $FILE=$ARGV[0]; #open Fails to open the file $FILE 

$FILE=$ARGV[0];  #Works Fine with Global $FILE 
open(FILE) 
    or 
die "\n ". "Cannot Open the file specified :ERROR: $!". "\n"; 
+6

Questo stile di Perl è ** modo ** obsoleto. Sarebbe molto meglio fare aprire il mio $ file, "<", $ ARGV [0] ... o meglio ancora non chiamare affatto aperto e solo leggere da ARGV.(Perl presuppone che gli argomenti siano file da aprire per l'input e li apre automaticamente per te.) –

+1

Unario aperto è documentato per funzionare solo sulle variabili del pacchetto. – tchrist

+0

@ William: Non dovrebbe esserci una codifica lì? 'open (FH," <: encoding (UTF-8) ", $ pathname)' – tchrist

risposta

13

Unario aperto funziona solo su variabili pacchetto (globali). Questo è documentato su the manpage.

Un modo migliore per aprire un file per la lettura sarebbe:

my $filename = $ARGV[0];   # store the 1st argument into the variable 
open my $fh, '<', $filename or die $!; # open the file using lexically scoped filehandle 

print <$fh>; # print file contents 

P.S. utilizzare sempre strict e warnings durante il debug degli script Perl.

+2

Questa risposta manca il punto. La semplice domanda era perché unario open funziona solo con le variabili del pacchetto. La semplice risposta è che è perché è così documentata. Tutto il resto è glassato su una torta mancante. – tchrist

+0

@tchrist: ok, ho aggiunto questo alla risposta –

+0

Grazie. Di solito non rispondo alle risposte che hanno fatto un buon tentativo (ecco perché non l'ho fatto qui). Preferisco indicare cosa hanno perso. Grazie per averlo risolto – tchrist

7

È tutto in perldoc -f open:

Se ESPR viene omessa, la variabile scalare dello stesso nome il FILEHANDLE. (Si noti che lessicali variabili - quelle dichiarate con "my" - non funzionerà per questo scopo, così se si sta utilizzando il "mio", specificare ESPR nella chiamata per aprire.)

Si noti che questo non è un ottimo modo per specificare il nome del file. Come puoi vedere, ha un forte vincolo sul tipo di variabile in cui si trova, e la variabile globale che richiede o il filehandle globale che apre di solito è meglio evitare.

Utilizzando un filehandle lessicale mantiene la sua portata in controllo, e maniglie chiusura automatica:

open my $fh, '<', "filename" or die "string involving $!"; 

E se si sta prendendo che il nome del file dalla riga di comando, si potrebbe fare a meno che open o qualsiasi gestire completamente e utilizzare l'operatore normale <> per leggere dagli argomenti della riga di comando o STDIN. (vedere i commenti per ulteriori informazioni al riguardo)

+0

Buon punto: di solito è un molto meglio usare l'ARGV magico di un open esplicito. Ma aggiungi 'if (! @ARGV && -t STDIN) {warn" $ 0: leggendo da stdin ... \ n "}' per aiutare le persone i cui sistemi non hanno un proprio carattere '^ T'tty. Tuttavia, la magia ARGV usa solo lo stdin quando '@ ARGV' è inizialmente vuoto, non quando è esaurito; la tua risposta suggerisce il contrario. – tchrist

+0

@tchrist: sì e no ... dopo '<> 'esaurito ARGV e restituito undef una volta (cosa stavi dicendo), ricomincerà da capo, con un @ARGV vuoto se non hai fatto nulla a riguardo, quindi ricadere su STDIN (cosa stavo dicendo). Ammetterei che la maggior parte delle persone non supererà il primo undef spontaneamente e modificherà. –

+0

Um, I ** do ** so come '<>' funziona. :) – tchrist

6
use strict; 
use warnings; 

my $file_name = shift @ARGV; 
open(my $file, '<', $file_name) or die $!; 
… 
close($file); 

Usare sempre strict e warnings. Se uno di loro si lamenta, correggi il codice, non commentare la direttiva. È anche possibile use autodie evitare l'esplicito or die dopo l'apertura, vedere autodie.

+1

+1 e deve essere ripetuto: se "strict" si lamenta, significa che è necessario correggere il codice, non che è necessario commentare 'strict'. –

+0

L'ho detto prima, lo dirò di nuovo: * Questa risposta manca il punto. La semplice domanda era perché unario open funziona solo con le variabili del pacchetto. La semplice risposta è che è perché è così documentata. Tutto il resto è glassato su una torta mancante. * Inoltre, hai dimenticato di specificare la codifica come in 'open (FH," <: encoding (UTF-8) ", $ path)'. E se si è così attenti, non si dovrebbe testare anche '@ ARGV' per la ragionevolezza? Infine, come puoi sapere che fanno ** NON ** vuoi consentire nomi di file come '-' nella maniera standard di Unix di specificare std {in, out, whatever}? – tchrist

+1

Inoltre, questo è davvero un brutto idioma. Perl gestisce già l'apertura automatica dei file elencati come argomenti tramite ARGV. In perl, non c'è quasi mai una buona ragione per aprire esplicitamente un file il cui nome è dato in @ARGV –

3

Da Perl's docs for open()

Se ESPR viene omessa, la variabile scalare dello stesso nome di FILEHANDLE. (Si noti che le variabili lessicali - quelli dichiarati con il mio - non funzionerà per tale scopo;. Quindi se si sta usando il mio, specificare ESPR nella chiamata per aprire)

+0

Succinto, corretto e al punto. – tchrist