Bri*_*anH 3 perl file-io perl-module perl-context
我是File :: Slurp模块的新手,在我第一次使用它时,它没有给出我期望的结果.我花了一段时间才弄明白,所以现在我对我为何看到这种行为感兴趣.
我对File :: Slurp的调用如下所示:
my @array = read_file( $file ) || die "Cannot read $file\n";
Run Code Online (Sandbox Code Playgroud)
我包含了"die"部分,因为我习惯在打开文件时这样做.我的@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.
'
Run Code Online (Sandbox Code Playgroud)
为什么是|| 死有所作为?我有一种感觉,这可能更像是一个Perl优先级问题而不是File :: Slurp问题.我查看了File :: Slurp模块,如果出现问题,它看起来像是设置为croak,所以我想正确的方法是允许File :: Slurp为你呱呱叫.现在我只是好奇为什么我看到这些差异.
布尔运算符或运算符||比赋值运算符更紧密绑定,并将函数调用放入标量上下文中.
my @array = read_file( $file ) || die "Cannot read $file\n";
Run Code Online (Sandbox Code Playgroud)
这就是说:尝试读取文件,并返回文件的串联或"返回" die作为第一个元素@array.你不会死,因为它读取文件并返回一个真值,尽管是一个标量值.
标准用法是语句或运算符(or),如下所示:
my @array = read_file( $file ) or die "Cannot read $file\n";
Run Code Online (Sandbox Code Playgroud)
这会尝试@array在列表上下文中进行分配,然后在标量上下文中评估已分配的列表,从而产生数组中的项目数.因此,首先分配数组,然后不要死,因为数组有条目.
第二种形式不会尝试将"返回"分配给die,@array因为首先完成赋值,因此@array要么保存文件的行,要么是空数组.
请注意文档File::Slurp read_file说:
在列表上下文中,它将返回一个行列表(使用$ /的当前值作为分隔符,包括对段落模式设置为''时的支持).在标量上下文中,它将整个文件作为单个标量返回.[ 斜体矿 ]
并给出以下示例:
my $text = read_file( 'filename' ) ;
my @lines = read_file( 'filename' ) ;
Run Code Online (Sandbox Code Playgroud)
但这些是最简单的情况,也是最基本的语境表达.分配给某种类型的变量并不能确保@lines无论周围的代码如何都将在列表上下文中分配.
该||操作员将其左侧操作数的布尔(标量)方面:
C风格的逻辑或
二进制
||执行短路逻辑OR运算.也就是说,如果左操作数为true,则甚至不评估右操作数.标量或列表上下文如果被计算,则向下传播到右操作数.
你也可以凭经验发现这个:
#! /usr/bin/perl
sub lhs {
my $ctx = wantarray;
if (defined $ctx) {
if ($ctx) { "list" }
else { "scalar" }
}
else { "void" }
}
print lhs || 0, "\n";
Run Code Online (Sandbox Code Playgroud)
输出:
$ ./or-ctx.pl scalar
要修复您的程序,您可以稍微修改它:
my @array = eval { read_file("/etc/issue") };
die unless @array;
Run Code Online (Sandbox Code Playgroud)
仅当您想要添加到错误消息(存储在特殊变量$@之后eval)时才需要这样做,因为如果出现问题read_file则会die.