命令行参数传递0时出现问题

9

我刚注意到perl5(5.10.0)的一个奇怪行为,当我将0作为命令行参数传递给脚本时,它将其分配给一个变量。我遇到的问题是,如果我在脚本中给变量一个默认值,该默认值大于0,比如1,那么我可以传递任何值,除了0以外,来覆盖默认值1。

以下是我使用的“test.pl”的代码:

#!/usr/bin/perl -w  
my $x = shift || 1;  
print "x is $x\n";  

以下是我测试时使用的命令和输出结果:
$ ./test.pl 2  
x is 2  
$ ./test.pl 0  
x is 1  

如果有人能够解释一下这个问题,我会非常感激。谢谢。(wwl)

5个回答

15

如果您希望在未提供参数的情况下,$x 的值为 "1",请使用以下代码:

my $x = shift // 1;  

从perldoc perlop获取:

"//"与"||"完全相同,除了它会检测左侧是否被定义,而不是它的真值。

注意:自5.10版(于2007年12月18日发布)起,可以使用定义或运算符。


我有一种感觉,这是在相当近期的Perl版本中引入的,你能说出是哪个版本吗?然后我会点赞。 - j_random_hacker
@gbacon:谢谢。由于我们中的许多人仍在使用早期版本,您能否在您的回答中提到这一点呢,Eugene Y?谢谢。 - j_random_hacker
感谢所有回答的人。我没想到会这么快得到答案。谢谢,尤金,我猜你是第一个回答的人。 - Wayne

7
表达式shift || 1会在左侧为“false”时选择右侧。由于您传递的是0,它被视为“false”,因此$x的值最终变成了1。

6

最佳方法是 Eugene 和 Alexandr 的回答中的方法,但如果你使用的是旧版 Perl,请使用以下方法:

my $x = shift;
$x = 1 unless defined $x;

因为你有一个可选参数,所以可以在标量上下文中检查@ARGV以检查有多少个命令行参数存在。如果存在,则使用它,否则回退到默认值:

my $x = @ARGV ? shift : 1;

3

使用定义或运算符,因为字符串“0”被定义了,但不被视为真。

#!/usr/bin/perl -w  
my $x = shift // 1;  
print "x is $x\n";  

是的,但正如gbacon在其他评论中提到的那样,这需要Perl 5.10或更高版本。 - j_random_hacker
2
j_random_hacker: Wayne正在使用5.10.0版本,该版本已经发布2.5年了。 - Alexandr Ciornii

0
在这行代码中 my $x = shift || 1; 中,shift 操作失败了,因此条件逻辑 OR || 被执行并将其赋值为 1... 根据 shift 页面上的说明,该值应该是 0,这意味着空数组....

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接