7

我现在正在课间休息,并决定花时间学习 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);after的存在<STDIN>;

现在,作者chomp在前面的例子中使用过,但他并没有真正涵盖chomp在做什么。所以,我在 www.perlmeme.org 上找到了这个答案:

chomp()函数将(通常)从字符串末尾删除任何换行符。我们通常说的原因是它实际上删除了与$/(输入记录分隔符)的当前值匹配的任何字符,并且$/默认为换行符。


无论如何,我的问题是:

  1. 删除了哪些换行符?Perl 会自动将 a 添加"\n"到来自 的输入<STDIN>吗?我只是有点不清楚,因为当我读到“它实际上删除了任何与”的当前值匹配的字符时$/,我不禁想“我不记得$/在我的代码中的任何地方放了一个”。

  2. 我想尽快制定最佳实践 - 最好总是chomp在之后包含,<STDIN>或者是否存在不必要的场景?

4

5 回答 5

9

<STDIN>读取到输入字符串的末尾,如果您按回车键输入,则该字符串包含换行符,您可能会这样做。

chomp删除字符串末尾的换行符。 $/是一个您可能不必担心的变量(如您所见,默认为换行符);它只是告诉 perl 什么是“输入记录分隔符”,我假设这意味着它定义了<FILEHANDLE>读取的距离。您现在几乎可以忘记它,这似乎是一个高级主题。只是假装chomp咬掉尾随的换行符。老实说,我以前从未听说$/过。

至于您的另一个问题,通常总是 chomp 变量并根据需要添加换行符通常更干净,因为您并不总是知道变量是否有换行符;通过总是咀嚼变量,你总是得到相同的行为。在某些情况下它是不必要的,但如果你不确定它不会伤害chomp它。

希望这可以帮助!

于 2011-09-03T00:59:46.960 回答
3

好的,从 1) 开始,perl 不会\n在输入中添加任何内容。Enter输入完号码后是你打的。如果您不指定$/\n则将放置一个默认值(至少在 UNIX 下)。

从 2) 开始,只要输入来自用户,或者当您想要删除行结束字符(例如,从文件中读取),就需要 chomp。

最后,您得到的错误可能来自 perl 不理解 last 的双引号内的变量print,因为它确实有一个_字符。尝试按如下方式编写字符串:

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

(注意{}最后一个变量)。

于 2011-09-03T01:03:34.170 回答
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/
于 2011-09-03T13:21:02.203 回答
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,而且我在五分钟前就达到了哈希值。

于 2011-09-03T01:01:37.367 回答
0

尽管这可能很明显,但仍然值得一提的是为什么chomp这里需要它。

创建的哈希包含 4 个查找键:"Me""Home""Emergency""Lookup"

$input从 中指定时<STDIN>,它将包含"Me\n""Me\r\n"或其他一些行尾变体,具体取决于所使用的操作系统。

未初始化值错误的出现是因为"Me\n"哈希中不存在该键。这就是为什么chomp需要:

my $input = <STDIN>; # "Me\n" --> Key DNE, $name_number{$input} not defined
chomp $input;        # "Me"   --> Key exists, $name_number{$input} defined
于 2011-09-03T10:00:38.017 回答