2011-09-03 13 views
7

Sono in pausa dalle lezioni in questo momento e ho deciso di passare il mio tempo ad imparare Perl. Sto lavorando con Beginning Perl (http://www.perl.org/books/beginning-perl/) e sto finendo gli esercizi alla fine del terzo capitolo.Sto cercando qualche chiarimento sul chomp

Uno degli esercizi ha chiesto di "Memorizzare i numeri di telefono importanti in un hash." Scrivere un programma per cercare i numeri in base al nome della persona. "

In ogni caso, mi ero messo a punto questo:

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

my %name_number= 
(
Me => "XXX XXX XXXX", 
Home => "YYY YYY YYYY", 
Emergency => "ZZZ ZZZ ZZZZ", 
Lookup => "411" 
); 

print "Enter the name of who you want to call (Me, Home, Emergency, Lookup)", "\n"; 
my $input = <STDIN>; 
print "$input can be reached at $name_number{$input}\n"; 

E semplicemente non avrebbe funzionato. Ho continuato a ottenere questo messaggio di errore: (.) ​​

L'utilizzo di valore non inizializzato in concatenazione o stringa in hello.plx linea 17, la linea 1

Ho provato a giocare con il codice un po 'di più, ma ogni "soluzione" sembrava più complessa della "soluzione" che veniva prima. Alla fine, ho deciso di verificare le risposte.

L'unica differenza tra il mio codice e la risposta era la presenza di chomp ($input); dopo <STDIN>;.

Ora, l'autore ha utilizzato chomp nell'esempio precedente, ma in realtà non ha spiegato cosa stava facendo chomp. Così, ho trovato questa risposta su www.perlmeme.org:

La funzione chomp() rimuoverà (di solito) qualsiasi carattere di nuova riga dal alla fine di una stringa. Il motivo per cui si dice di solito è che in realtà rimuove qualsiasi carattere che corrisponde al valore attuale dei $/ (il separatore di record in ingresso ), e $/ default ad una nuova riga ..


In ogni caso, le mie domande sono :

  1. Quali newline vengono rimossi? Perl aggiunge automaticamente "\n" all'input da <STDIN>? Sono solo un po 'poco chiaro perché quando leggo "rimuove effettivamente qualsiasi carattere che corrisponda al valore corrente di $/", non posso fare a meno di pensare "Non ricordo di aver inserito un codice $/ in nessuna parte del mio codice."

  2. Mi piacerebbe sviluppare le migliori pratiche il prima possibile: è sempre meglio includere chomp dopo il <STDIN> o ci sono scenari in cui non è necessario?

+2

'perldoc -f chomp' o [perlfunc] (http://perldoc.perl.org/perlfunc.html) –

+0

Okay, quindi la voce chomp FAQ di Perlmeme (http: //www.perlmeme.org/faqs/manipulating_text/chomp.html) risponde alla maggior parte della mia prima domanda. Cioè, le FAQ mi portano a credere che Perl faccia automaticamente una nuova riga (non necessariamente in "\ n" ma una nuova riga sempre uguale). Ma lo capisco correttamente? – krebshack

+0

Continuando con il collegamento da perlfunc: [chomp] (http://perldoc.perl.org/functions/chomp.html) che copre l'uso del separatore. –

risposta

9

<STDIN> legge alla fine della stringa di input, che contiene una nuova riga se si preme il ritorno di entrarvi, che probabilmente si fa.

chomp rimuove la nuova riga alla fine di una stringa. $/ è una variabile (come hai trovato, di default a newline) di cui probabilmente non devi preoccuparti; dice solo perl cosa è il 'separatore di record di input', che presumo significa che definisce quanto lontano legge <FILEHANDLE>. Puoi quasi dimenticarlo per ora, sembra un argomento avanzato.Fai finta che lo chomp mordi una nuova riga finale. Onestamente, non ho mai nemmeno sentito parlare di $/ prima.

Come per la tua altra domanda, è generalmente più pulito sempre chomp variabili e aggiungi newline come necessario in seguito, perché non si sa sempre se una variabile ha una nuova riga o no; tagliando sempre le variabili si ottiene sempre lo stesso comportamento. Ci sono scenari in cui non è necessario, ma se non sei sicuro che non possa fare male a chomp it.

Spero che questo aiuti!

+1

" legge fino alla fine della stringa di input, che contiene una nuova riga se si preme Invio per inserirlo, cosa che probabilmente si fa". Questo chiarisce molto. Non ricordo l'autore che ha menzionato il fatto che premendo Invio dopo aver inserito il mio input su conterrà automaticamente una nuova riga. Anche se questo spiega perché è stata creata una nuova riga anche se non ne avevo (consapevolmente) scritto uno nel codice. Grazie per l'aiuto. – krebshack

+1

@kreb - questo non è proprio Perl specifico - il comportamento di nuova riga è specifico per il sistema operativo (e la maggior parte dei sistemi operativi lo farà, anche se diversi sistemi operativi hanno linee di riepilogo differenti - è qui che entra $/'. Windows/DOS newline è diverso da Unix newline Fortunatamente per te, Perl Just Works - vale a dire, Windows Perl imposterà '$ /' su Windows newline.Vedi l'eccellente risposta di shawnhcorey sotto – DVK

0

Credo che le migliori pratiche qui è scrivere:

chomp(my $input = <STDIN>); 

Ecco rapido esempio di come chomp funzione ($/ significato è spiegato qui) lavori di rimuovere solo una finale nuova linea (se del caso):

chomp (my $input = "Me\n"); # OK 
chomp ($input = "Me"); # OK (nothing done) 
chomp ($input = "Me\n\n"); # $input now is "Me\n"; 
chomp ($input); # finally "Me" 

print "$input can be reached at $name_number{$input}\n"; 

BTW: La cosa divertente è che sto imparando anche Perl e ho raggiunto gli hash cinque minuti fa.

+0

Oh, è divertente.Quali risorse stai usando? Trovo che sia utile avere accesso a molti tutorial/libri/siti web come posso quando sto imparando qualcosa di nuovo – krebshack

+0

@krebshack: Sto usando principalmente [Learning Perl] (http://oreilly.com/catalog/0636920018452?green=c142e8ee-fefc-4f4d- 80d1-fb6d1f20e787 & cmp = af-mybuy-0636920018452.IP) (da [Safari Books] (http://my.safaribooksonline.com/)) e talvolta [perldoc] (http://perldoc.perl.org/). –

+0

Dovrò ritirarlo quando arriverà il mio prossimo stipendio. Non ho avuto altro che expe positiva rienze con O'Reilly's. – krebshack

3

OK, a partire da 1), perl non aggiunge alcun \n all'ingresso. Sei tu che hai colpito Inserisci quando hai finito di inserire il numero. Se non si specifica $/, verrà inserito un valore predefinito di \n (almeno UNIX, almeno).

A partire da 2), il chomp sarà necessario ogni volta che l'input proviene dall'utente o ogni volta che si desidera rimuovere il carattere di fine riga (lettura da un file, ad esempio).

Infine, l'errore che si sta verificando potrebbe derivare da perl non comprendere la variabile tra virgolette dell'ultimo print, perché ha un carattere _. Prova a scrivere la stringa come segue:

print "$input can be reached at ${name_number{$input}}\n"; 

(notare il {} intorno l'ultima variabile).

+0

Non ne sono sicuro. Ho provato a sostituire la mia "stampa" $ input ... "stringa con" con stampa "" $ input può essere raggiunto a $ {name_number {$ input}} \ n ";" e ha restituito gli stessi risultati quando è stato seguito da chomp. Ha anche restituito lo stesso messaggio di errore quando non è stato seguito da chomp. Ma, dovresti scrivere degli archi come hai dimostrato di essere un'abitudine in cui dovrei entrare? – krebshack

+0

Perché le doppie * doppie * virgolette? Riguardo le variabili, sì, le variabili con caratteri speciali come '_' dovrebbero essere circondate da' {} 'se tra virgolette doppie. –

+0

Ok, è bello saperlo. Toglierò le doppie virgolette. È un errore di battitura. – krebshack

0

Anche se può essere ovvio, vale ancora la pena menzionare perché è necessario il chomp qui.

L'hash creata contiene 4 chiavi di ricerca: "Me", "Home", "Emergency" e "Lookup"

Quando $input è specificato da <STDIN>, sarà contengono "Me\n", "Me\r\n" o qualche altra variante di fine riga a seconda del sistema operativo è in uso.

L'errore di valore non inizializzato si verifica perché la chiave "Me\n" non esiste nell'hash. E questo è il motivo per cui è necessario il chomp:

my $input = <STDIN>; # "Me\n" --> Key DNE, $name_number{$input} not defined 
chomp $input;  # "Me" --> Key exists, $name_number{$input} defined 
2

<STDIN> è una notazione scorciatoia per readline(*STDIN);. Quello che readline() fa legge l'handle del file finché non incontra il contenuto di $/(aka $ INPUT_RECORD_SEPARATOR) e restituisce tutto ciò che ha letto compreso il contenuto di $ /. Quello che chomp() fa è rimuovere l'ultimo contenuto di occorrenza di $ /, se presente.

Il contenuto è spesso chiamato carattere di fine riga ma può essere composto da più di un carattere. Su Linux, contiene un carattere LF ma su Windows, contiene CR-LF.

See:

perldoc -f readline 
perldoc -f chomp 
perldoc perlvar and search for /\$INPUT_RECORD_SEPARATOR/ 
Problemi correlati