2014-11-06 12 views
6

sto ottenendo:Perl avvertimento: l'uso di valore non inizializzato in aderire o stringa

"Use of uninitialized value in join or string at ./test_script.pl line 69, <fh> line 91." 

Il codice creazione di questo avviso è qui:

# Write results of SQL execution to output file 
if ([email protected]) { print "\n DB Error : ", [email protected]; exit; } 
open(FH, ">$output_file") or 
     die "\n cannot write to the file $output_file. Check the file permissions"; 
while(my @row= $sth->fetchrow_array) { 
     print FH join($delimiter, @row). "\n"; 
} 

E 'venuta dalla "stampa .. Unisci .... "linea nel blocco" while ", ma non sono sicuro al 100% su cosa lo sta causando e su come correggerlo.

Il delimitatore $ è inizializzato in precedenza come il mio $ delimitatore = "|" e @row sta ottenendo i suoi valori dall'operazione $ sth nella riga precedente.

Si tratta di un problema di "tempistica" relativo ai valori @row o si tratta di qualcosa nel file di query SQL effettivamente elaborato, come indicato dalla parte "< fh> 91" dell'avviso? Qualche idea su come posso evitare gli avvertimenti? BTW, lo script funziona bene, genera solo un avviso per ogni valore @row recuperato, che crea un'enorme quantità di avvisi su un grande set di dati pull ...

+0

come si presenta la query o il codice che ha generato la query? – SBH

+1

Dimostra a te stesso che $ delimitatore ha un valore. Aggiungilo subito prima della stampa: 'print" delimiter >>> $ delimitatore <<< \ n ";' – toolic

+4

Se dovessi indovinare, una delle colonne in '@ row' è' NULL'. – nandhp

risposta

11

può contenere alcuni elementi che hanno un valore non definito , probabilmente perché una o più colonne del database che popolato @row era NULL. Il comportamento può essere imitato pur utilizzando join in un semplice Perl-liner simili:

perl -we 'my @array = ("Hello",undef,"world!"); print join("|",@array) . "\n";' 

l'uscita che produrrà è:

Use of uninitialized value $array[1] in join or string at -e line 1. 
Hello||world! 

la ragione per cui questo accade è perché join sta cercando di unire un valore che non si stringa senza essere aggiornato da "non definito" a "definito". Stringendo undef si genera questo messaggio di avviso per avvisare che si sta facendo qualcosa di non intenzionale e non corretto.

Un esempio ancora più semplice potrebbe essere questo:

$ perl -we 'my $scalar; print "$scalar\n";' 
Use of uninitialized value $scalar in concatenation (.) or string at -e line 1. 

Anche in questo caso, si ottiene l'avvertimento perché stiamo interpolando un valore indefinito in una stringa. L'interpolazione causa la stringificazione e la stringificazione di un valore indefinito genera generalmente un avvertimento per farti sapere che potresti aver fatto un errore.

Se non ti dispiace in silenzio l'aggiornamento delle undef 's su una stringa vuota, si potrebbe fare questo:

print FH join($delimiter, map { defined ? $_ : '' } @row) . "\n"; 

questo pre-processi @row prima di consegnarlo a join(). Per ogni elemento in @row, se l'elemento ha un valore non definito, tale valore viene sostituito da una stringa vuota, che è definita ma visivamente silenziosa.

L'altra possibilità è che $delimiter non è definito. Provalo per questo stampandolo, e se ciò si verifica, i passaggi che dovrai eseguire per risolverlo sono semplicemente assicurarti che contenga effettivamente un valore.

Basta mettere a tacere gli avvertimenti in un ambito lessicale stretto potrebbe essere ok, anche se da un punto di vista filosofico, un metodo rimuove la causa e l'altro rimuove uno dei sintomi. Il metodo "no warnings 'uninitialized'; descritto altrove fa proprio questo; silenzia l'avviso.Lo faresti quando sai che stai facendo qualcosa di perfettamente Ok, ma sai anche che Perl ti avviserà perché molte volte è un errore. Questa potrebbe essere una situazione del genere; si può essere perfettamente contenti semplicemente lasciando che la stringificazione silenziosa di un valore indefinito avvenga all'interno dello join. E se è così, vai avanti e soffoca l'avvertimento. La cosa più importante è che tu sappia cosa significa, verifica cosa lo sta causando e poi prendi una decisione informata su cosa fare al riguardo.

+1

Se qualcuno lo trova, l'uso di definito è ambiguo come mostrato. deve essere mappato {definito $ _? $ _: ''} – mark

+0

'perl' non ha alcuna ambiguità qui, e il fatto che' defined' ricada all'utilizzo di '$ _' come parametro in assenza di altri parametri è discusso in' perldoc -f defined'. L'uso dell'operatore ternario non è ambiguo. Ed è documentato che 'map' popola' $ _' come alias per l'elemento di lista su cui sta iterando. Questo si riduce a un problema di stile, forse menzionato da qualche parte in PBP. – DavidO

+0

E infatti, sì, si tratta di un problema PBP inserito nell'intestazione * Iterator Variables *, pagina 105-107. Non sembra che questo suggerimento PBP citi l'ambiguità, ma piuttosto la leggibilità. E se la leggibilità fosse la preoccupazione, non sarei in disaccordo. – DavidO

Problemi correlati