我现在正在上课,决定花时间学习Perl。我正在使用Beginning Perl(http://www.perl.org/books/beginning-perl/),我将在第三章结束时完成练习。
其中一个练习要求我“将您的重要电话号码存储在哈希中。编写程序以按人名查找数字。”
无论如何,我想出了这个:
#!/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";
它就行不通了。我不断收到此错误消息:
在串联(。)中使用未初始化的值或在hello.plx中使用字符串 第17行,第1行
我尝试了更多的代码,但每个“解决方案”看起来比之前的“解决方案”更复杂。最后,我决定检查答案。
我的代码和答案之间的唯一区别是在chomp ($input);
之后存在<STDIN>;
。
现在,作者在前面的示例中使用了chomp
,但他并没有真正涵盖chomp
正在做的事情。所以,我在www.perlmeme.org上找到了这个答案:
chomp()
函数将删除(通常)任何换行符 一个字符串的结尾。我们通常说的原因是它实际上 删除与$/
的当前值匹配的任何字符(输入 记录分隔符),$/
默认为换行符..
无论如何,我的问题是:
哪些换行符被删除? Perl是否会自动将"\n"
附加到<STDIN>
的输入中?我只是有点不清楚,因为当我读到“它实际上删除了与$/
的当前值相匹配的任何字符时,我忍不住想”我不记得放$/
在我的代码中的任何地方。“
我希望尽快制定最佳做法 - 最好是在chomp
之后始终包含<STDIN>
,还是有不必要的情况?
答案 0 :(得分:9)
<STDIN>
读到输入字符串的末尾,如果你按回车键输入它,你可能会这样做。
chomp
删除字符串末尾的换行符。 $/
是一个变量(如您所见,默认为换行符),您可能不必担心;它只是告诉perl'输入记录分隔符'是什么,我假设它意味着它定义了<FILEHANDLE>
读取的距离。你现在几乎可以忘记它,它似乎是一个高级主题。只是假装chomp
扼杀一个尾随换行符。老实说,我以前从未听说过$/
。
至于你的另一个问题,通常更清楚的是总是选择变量并在以后根据需要添加换行符,因为你并不总是知道变量是否有换行符;通过总是扼杀变量,你总是得到相同的行为。在某些情况下,这是不必要的,但如果您不确定它不会对chomp
造成伤害。
希望这有帮助!
答案 1 :(得分:3)
好的,从1开始,perl不会在输入处添加任何\n
。完成输入数字后,按 Enter 。如果您未指定$/
,则将放置默认值\n
(至少在UNIX下)。
从2开始),只要输入来自用户,或者只要你想删除行结束字符(例如从文件中读取),就需要chomp。
最后,您获得的错误可能来自perl,而不是在最后print
的双引号内理解您的变量,因为它确实有_
个字符。尝试按如下方式编写字符串:
print "$input can be reached at ${name_number{$input}}\n";
(注意最后一个变量周围的{}
。)
答案 2 :(得分:2)
<STDIN>
是readline( *STDIN );
的快捷符号。 readline()所做的是读取文件句柄,直到遇到$ /(又名$ INPUT_RECORD_SEPARATOR)的内容并返回它已读取的所有内容,包括$ /的内容。 chomp()
执行的操作是删除$ /的最后一次出现内容(如果存在)。
内容通常称为换行符,但可能由多个字符组成。在Linux上,它包含一个LF字符,但在Windows上,它包含CR-LF。
请参阅:
perldoc -f readline
perldoc -f chomp
perldoc perlvar and search for /\$INPUT_RECORD_SEPARATOR/
答案 3 :(得分:0)
我认为这里的最佳做法是写:
chomp(my $input = <STDIN>);
以下是chomp
函数($/
含义在那里解释)的快速示例,只删除一个尾随的新行(如果有的话):
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";
顺便说一句:有趣的是,我也在学习Perl,五分钟前我就到了哈希。
答案 4 :(得分:0)
虽然可能很明显,但仍然值得一提为什么这里需要chomp
。
创建的哈希包含4个查找键:"Me"
,"Home"
,"Emergency"
和"Lookup"
从$input
指定<STDIN>
后,它将包含"Me\n"
,"Me\r\n"
或其他一些行结尾变体,具体取决于正在使用的操作系统。< / p>
出现未初始化的值错误,因为哈希中不存在"Me\n"
键。这就是为什么需要chomp
:
my $input = <STDIN>; # "Me\n" --> Key DNE, $name_number{$input} not defined
chomp $input; # "Me" --> Key exists, $name_number{$input} defined