2011-09-03 15 views
7

Estoy en el descanso de las clases en este momento y decidí pasar el tiempo aprendiendo Perl. Estoy trabajando con Beginning Perl (http://www.perl.org/books/beginning-perl/) y estoy terminando los ejercicios al final del capítulo tres.Estoy buscando alguna aclaración sobre chomp

Uno de los ejercicios solicitó que "almacene sus números telefónicos importantes en un hash." Escriba un programa para buscar números por el nombre de la persona ".

De todos modos, yo había llegado con esto:

#!/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"; 

Y simplemente no funcionaría. Seguí recibiendo este mensaje de error: (.) ​​

Uso del valor no inicializado en la concatenación o cuerda en hello.plx línea 17, línea 1

He intentado jugar con el código un poco más, pero cada "solución" parecía más compleja que la "solución" anterior. Finalmente, decidí verificar las respuestas.

La única diferencia entre mi código y la respuesta fue la presencia de chomp ($input); después de <STDIN>;.

Ahora, el autor ha usado chomp en el ejemplo anterior pero realmente no cubrió lo que chomp estaba haciendo. Por lo tanto, he encontrado esta respuesta en www.perlmeme.org:

La función chomp() eliminará (por lo general) cualquier carácter de nueva línea de el final de una cadena. La razón por la que decimos por lo general es que en realidad elimina cualquier carácter que coincide con el valor actual de $/ (la entrada separador de registro), y $/ por defecto a una nueva línea ..


De todos modos, mis preguntas son :

  1. ¿Qué nuevas líneas se están eliminando? ¿Perl agrega automáticamente un "\n" a la entrada de <STDIN>? Estoy un poco confuso porque cuando leí "realmente elimina cualquier personaje que coincida con el valor actual de $/", no puedo evitar pensar "No recuerdo haber puesto $/ en ningún lugar de mi código".

  2. Me gustaría desarrollar las mejores prácticas lo antes posible. ¿Es mejor incluir siempre chomp después de <STDIN> o hay situaciones en las que no es necesario?

+2

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

+0

bien, así que la entrada chomp en de Perlmeme FAQ (http: //www.perlmeme.org/faqs/manipulating_text/chomp.html) responde la mayor parte de mi primera pregunta. Es decir, las preguntas frecuentes me llevan a creer que Perl hace automáticamente una nueva línea (no necesariamente en "\ n" sino una nueva línea). ¿Pero estoy entendiendo eso correctamente? – krebshack

+0

Continuando con el enlace de perlfunc: [chomp] (http://perldoc.perl.org/functions/chomp.html) que cubre el uso del separador. –

Respuesta

9

<STDIN> lee hasta el final de la cadena de entrada, que contiene un salto de línea si pulsa retorno a entrar en él, que es probable que sí.

chomp quita la nueva línea al final de una cadena. $/ es una variable (como usted encontró, por defecto en la línea nueva) de la que probablemente no tenga que preocuparse; simplemente le dice a Perl qué es el 'separador de registros de entrada', lo que supongo significa que define cuánto lee <FILEHANDLE>. Puedes olvidarlo por ahora, parece un tema avanzado.Solo pretendo chomp domina una línea nueva posterior. Honestamente, nunca he oído hablar de $/ antes.

En cuanto a su otra pregunta, generalmente es más limpio que siempre muerda variables y agregue nuevas líneas según sea necesario más adelante, porque no siempre se sabe si una variable tiene una nueva línea o no; al masticar siempre las variables, siempre obtienes el mismo comportamiento. Hay escenarios en los que no es necesario, pero si no está seguro de que no puede dañarlo, chomp.

Espero que esto ayude!

+1

" lee hasta el final de la cadena de entrada, que contiene una nueva línea si presiona volver para ingresarla, lo cual probablemente haga". Eso aclara mucho. No recuerdo que el autor mencione que presionar return después de ingresar mi entrada en contendrá automáticamente una nueva línea. Aunque eso explica por qué se estaba creando una nueva línea, aunque no había escrito (conscientemente) una en el código. Gracias por tu ayuda. – krebshack

+1

@kreb - esto no es realmente específico de Perl - el comportamiento de la línea nueva es específico del sistema operativo (y la mayoría de los sistemas operativos lo harán, aunque diferentes sistemas operativos tienen líneas nuevas diferentes - ahí es donde entra '$ /'. Afortunadamente para ti, Perl Just Works, es decir, Windows Perl configurará '$ /' en la nueva línea de Windows. Consulta la excelente respuesta de shawnhcorey debajo de – DVK

0

Creo que la mejor práctica aquí es escribir:

chomp(my $input = <STDIN>); 

Aquí es rápido ejemplo de cómo chomp función ($/ significado se explica allí) obras de eliminación de un solo arrastra nueva línea (si lo hay):

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"; 

Por cierto: Lo curioso es que también estoy aprendiendo Perl y alcancé hashes hace cinco minutos.

+0

Oh, eso es divertido. ¿Qué recursos estás usando? Me parece útil tener acceso a muchos tutoriales/libros/sitios web como puedo cuando estoy aprendiendo algo nuevo. – krebshack

+0

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

+0

Tendré que recoger eso cuando llegue mi próximo cheque de pago. No he tenido nada más que una experiencia positiva. relaciones con O'Reilly. – krebshack

3

OK, a partir de 1), perl no agrega ningún \n a la entrada. Es usted quien presionó Ingrese cuando termine de ingresar el número. Si no especifica $/, se pondrá un valor predeterminado de \n (al menos, en UNIX).

A partir de 2), se necesitará chomp siempre que la entrada provenga del usuario, o siempre que quiera eliminar el carácter de final de línea (por ejemplo, leer un archivo).

Finalmente, el error que está obteniendo puede ser de perl que no entiende su variable dentro de las comillas dobles de la última print, porque tiene un carácter _. Trate de escribir la cadena de la siguiente manera:

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

(tenga en cuenta el {} alrededor de la última variable).

+0

No estoy seguro. Intenté reemplazar mi entrada "print" $ input ... "con" print "" $ input se puede llegar a $ {name_number {$ input}} \ n ";" y devolvió los mismos resultados cuando fue seguido por chomp. También devolvió el mismo mensaje de error cuando no fue seguido por chomp. Pero, ¿escribir cadenas como lo demostró es un hábito en el que debería meterme? – krebshack

+0

¿Por qué las comillas dobles * dobles *? Acerca de las variables, sí, las variables con caracteres especiales como '_' deben estar rodeadas por' {} 'si están entre comillas dobles. –

+0

Bien, eso es bueno saberlo. Eliminaré las comillas dobles dobles. Es un error tipográfico – krebshack

0

Aunque puede ser obvio, todavía vale la pena mencionar por qué es necesario el chomp aquí.

El hash creado contiene 4 claves de búsqueda: "Me", "Home", "Emergency" y "Lookup"

Cuando se especifica $input de <STDIN>, que va contienen "Me\n", "Me\r\n" o alguna otra variante de final de línea, dependiendo de qué sistema operativo es siendo utilizado.

El error de valor no inicializado se produce porque la clave "Me\n" no existe en el hash. Y es por eso que se necesita la chomp:

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

<STDIN> es una notación atajo para readline(*STDIN);. Lo que readline() hace es leer el manejador del archivo hasta que encuentra el contenido de $/(también conocido como $ INPUT_RECORD_SEPARATOR) y devuelve todo lo que ha leído, incluido el contenido de $ /. Lo que hace chomp() es eliminar los últimos contenidos de $ /, si están presentes.

El contenido a menudo se denomina carácter de nueva línea, pero puede estar compuesto por más de un carácter. En Linux, contiene un carácter LF, pero en Windows, contiene CR-LF.

Ver:

perldoc -f readline 
perldoc -f chomp 
perldoc perlvar and search for /\$INPUT_RECORD_SEPARATOR/ 
Cuestiones relacionadas