7

我完整的 perl 脚本是

chdir ("/etc" or die "cannot change: $!\n");
print  "\nCurrent Directory is $ENV{PWD} \n";

我得到了输出(不像预期的那样)

bash-3.2$ perl test.pl 

当前目录是/home

PS/home是我执行的地方test.pl

4

3 回答 3

12
  1. 您应该移出or diechdir(...)即:

    chdir("/etc") or die "cannot change: $!\n";
    

    使用您当前拥有的内容,"/etc" or die "cannot change: $!\n"首先评估表达式。它的结果是"/etc"并且die()永远不会被执行。or die()应该“应用于”chdir()调用,而不是其参数。

  2. 执行print(cwd);打印当前工作目录。不要忘记use Cwd;


use Cwd;

chdir("/etc") or die "cannot change: $!\n";
print(cwd);
于 2013-09-04T07:06:31.997 回答
5

Alex Shesterov给出了正确的答案,但由于这有一些有趣的细节,我将详细说明。这是文档or

二进制“或”返回两个周围表达式的逻辑析取。相当于|| 除了非常低的优先级。这使得它对控制流很有用:

print FH $data    or die "Can't write to FH: $!";

这意味着它会短路:仅当左表达式为假时才计算右表达式。

Perl 文档作者所说的“这意味着”是什么意思,我想我们永远不会知道,但句子的以下部分很重要:它短路了

在 Perl 中,“真”和“假”处理起来有点方便,因为只有少数假值,所有其他值都被认为是真。例如,undef, 0,空字符串和空列表是“假”值的示例。并且像这个问题"/etc"中的字符串这样的字符串永远不会是错误的。

将参数传递给函数/子例程时,使用列表。列表是一系列独立的陈述,例如:

"foo", "bar", "baz"  # three strings, foo bar baz
qw(foo bar baz)      # same thing
my @array = qw(foo bar baz);
@array;              # same thing, unless scalar context

但是,or运算符不会创建列表,而是强制在将语句传递给函数之前立即对其进行评估。所以,这就是发生的事情:

chdir ("/etc" or die "cannot change: $!\n");
#      ^^^^^^-- true value
--> "/etc" or die ? --> "/etc"
chdir("/etc");

你已经找到了这个经典错误的新版本。通常人们会这样做:

open my $fh, "<", "file" || die "Cannot open: $!";

这是同样的错误,在一个更微妙的版本中:逻辑或||运算符的优先级高于逗号运算符,这使得上述语句类似于:

open my $fh, "<", ( "file" || die "Cannot open: $!" );

这正是您遇到的问题:该die语句永远无法在逻辑上执行,因为具有文件名的字符串永远不会(除非它为空或零)为假。

于 2013-09-04T09:07:03.797 回答
0

此代码按您的预期工作:

#!/usr/bin/perl

use Cwd qw(chdir);

chdir ("/etc") or die "cannot change: $!\n";
print  "\nCurrent Directory is $ENV{PWD} \n";
于 2013-09-04T07:10:52.713 回答