3

我是 File::Slurp 模块的新手,在我的第一次测试中,它没有给出我期望的结果。我花了一段时间才弄清楚,所以现在我对为什么我会看到这种特定行为感兴趣。

我对 File::Slurp 的调用如下所示:

my @array = read_file( $file ) || die "Cannot read $file\n";

我包括了“死”部分,因为我习惯于在打开文件时这样做。我的@array 总是以数组的第一个元素中的文件的全部内容结束。最后我取出“|| die”部分,它开始按我预期的那样工作。

下面是一个例子来说明:

perl -de0

Loading DB routines from perl5db.pl version 1.22
Editor support available.

Enter h or `h h' for help, or `man perldebug' for more help.

main::(-e:1):   0
DB<1> use File::Slurp

DB<2> $file = '/usr/java6_64/copyright'

DB<3> x @array1 = read_file( $file )
0  'Licensed material - Property of IBM.'
1  'IBM(R) SDK, Java(TM) Technology Edition, Version 6'
2  'IBM(R) Runtime Environment, Java(TM) Technology Edition, Version 6'
3  ''
4  'Copyright Sun Microsystems Inc, 1992, 2008. All rights reserved.'
5  'Copyright IBM Corporation, 1998, 2009. All rights reserved.'
6  ''
7  'The Apache Software License, Version 1.1 and Version 2.0'
8  'Copyright 1999-2007 The Apache Software Foundation. All rights reserved.'
9  ''
10  'Other copyright acknowledgements can be found in the Notices file.'
11  ''
12  'The Java technology is owned and exclusively licensed by Sun Microsystems Inc.'
13  'Java and all Java-based trademarks and logos are trademarks or registered'
14  'trademarks of Sun Microsystems Inc.  in the United States and other countries.'
15  ''
16  'US Govt Users Restricted Rights - Use duplication or disclosure'
17  'restricted by GSA ADP Schedule Contract with IBM Corp.'
DB<4> x @array2 = read_file( $file ) || die "Cannot read $file\n";

0  'Licensed material - Property of IBM.
IBM(R) SDK, Java(TM) Technology Edition, Version 6
IBM(R) Runtime Environment, Java(TM) Technology Edition, Version 6

Copyright Sun Microsystems Inc, 1992, 2008. All rights reserved.
Copyright IBM Corporation, 1998, 2009. All rights reserved.

The Apache Software License, Version 1.1 and Version 2.0
Copyright 1999-2007 The Apache Software Foundation. All rights reserved.

Other copyright acknowledgements can be found in the Notices file.

The Java technology is owned and exclusively licensed by Sun Microsystems Inc.
Java and all Java-based trademarks and logos are trademarks or registered
trademarks of Sun Microsystems Inc.  in the United States and other countries.

US Govt Users Restricted Rights - Use duplication or disclosure
restricted by GSA ADP Schedule Contract with IBM Corp.
'

为什么|| 死有什么不同?我感觉这可能更像是 Perl 优先级问题,而不是 File::Slurp 问题。我查看了 File::Slurp 模块,如果出现问题,它似乎设置为 croak,所以我想正确的方法是让 File::Slurp 为你发声。现在我只是好奇为什么我会看到这些差异。

4

3 回答 3

9

布尔值运算符||比赋值运算符绑定得更紧密,并将函数调用放入标量上下文中

my @array = read_file( $file ) || die "Cannot read $file\n";

这就是说:尝试读取文件,并返回文件的串联或“返回”die作为@array. 你不会死,因为它读取了文件并返回了一个真值,尽管是一个标量值。

标准用法是语句或运算符 ( or),如下所示:

my @array = read_file( $file ) or die "Cannot read $file\n";

这尝试@array在列表上下文中分配,然后在标量上下文中评估分配的列表,产生数组中的项目数。因此,您首先分配数组,然后您不会因为数组有条目而死。

第二种形式不会尝试分配“返回” from dieto,@array因为分配是首先完成的,因此@array要么保存文件的行,要么是一个空数组。

请注意,文档File::Slurp read_file说:

列表上下文中,它将返回行列表(使用 $/ 的当前值作为分隔符,包括在设置为 '' 时支持段落模式)。在标量上下文中,它将整个文件作为单个标量返回。[斜体我的]

并给出以下例子:

    my $text = read_file( 'filename' ) ;
    my @lines = read_file( 'filename' ) ;

但这些是最简单的情况,也是最基本的上下文表达。@lines无论周围的代码如何,分配给某种类型的变量并不能确保在列表上下文中分配给它。

于 2010-06-02T14:02:42.817 回答
6

运算符将其||左侧操作数置于布尔(标量)上下文中:

C 风格的逻辑或

二进制||执行短路逻辑或运算。也就是说,如果左操作数为真,则甚至不计算右操作数。如果计算,标量或列表上下文会向下传播到正确的操作数。

您还可以凭经验发现这一点:

#! /usr/bin/perl

sub lhs {
  my $ctx = wantarray;
  if (defined $ctx) {
    if ($ctx) { "list" }
    else      { "scalar" }
  }
  else { "void" }
}

print lhs || 0, "\n";

输出:

$ ./或-ctx.pl
标量

要修复您的程序,您可以稍微修改它:

my @array = eval { read_file("/etc/issue") };
die unless @array;

仅当您要添加到错误消息(存储在$@之后的特殊变量中eval)时才需要这样做,因为如果出现问题,这read_file将是必需的die

于 2010-06-02T13:49:48.883 回答
4

你的问题已经回答了。作为旁注,首先,请记住,or并且and更适合流控制语句。然而,更重要的是,下面的检查

 my @array = read_file( $file ) || die "Cannot read $file\n";

完全没有必要。默认情况下,File::Slurp::read_file croak出错:

错误模式

您可以使用此选项来控制发生错误时 read_file 的行为方式。此选项默认为“呱呱”。您可以将其设置为“鲤鱼”或“安静”以不进行错误处理。

于 2010-06-02T15:41:14.963 回答