如何告诉perl打印到文件句柄而不是打印文件句柄?

时间:2012-12-01 11:53:18

标签: perl

我正试图围绕Perl处理print的参数解析的方式。

为什么会这样

print $fh $stufftowrite

按预期写入文件句柄,但

print($fh, $stufftowrite)

文件句柄写入STDOUT而不是?

我的猜测是它与print的文档中的警告有关:

  

小心不要使用左括号跟随print关键字,除非您希望相应的右括号终止print的参数;将括号括在所有参数周围(或插入一个+,但看起来不太好)。

我是否应该习惯第一种形式(这对我来说似乎不对,来自于所有使用围绕函数参数的括号的语言),还是有办法告诉Perl做我想做的事情? / p>

到目前为止,我已经在第一,第二和两个参数周围尝试了很多括号组合,但没有成功。

4 个答案:

答案 0 :(得分:18)

在列表

结构bareword (LIST1), LIST2表示"将函数bareword应用于参数LIST1",而bareword +(LIST1), LIST2可以,但不是必须表示"将bareword应用于组合列表LIST1, LIST2"的参数。这对于分组参数非常重要:

my ($a, $b, $c) = (0..2);
print ($a or $b), $c;  # print $b
print +($a or $b), $c; # print $b, $c

前缀+也可用于区分hashref与块,以及来自裸字的函数,例如:订阅哈希时:$hash{shift}返回shift元素,而$hash{+shift}调用函数shift并返回值为shift的哈希元素。

间接语法

在面向对象的Perl中,通常使用箭头语法调用对象上的方法:

$object->method(LIST);   # call `method` on `$object` with args `LIST`.

但是,有可能,但建议,使用将动词放在首位的间接表示法:

method $object (LIST);   # the same, but stupid.

因为类只是它们自身的实例(在语法意义上),所以你也可以调用它们的方法。这就是为什么

new Class (ARGS);  # bad style, but pretty

相同
Class->new(ARGS);  # good style, but ugly

但是,这有时会使解析器混淆,因此不建议使用间接样式。

但它确实暗示了印刷品的作用:

print $fh ARGS

相同
$fh->print(ARGS)

实际上,文件句柄$fh被视为类IO::Handle的对象。

(虽然这是一个有效的语法解释,但事实并非如此。IO::Handle的来源本身使用了行print $this @_;。打印函数只是定义了这个方式。)

答案 1 :(得分:13)

看起来你有一个错字。您在第二个print语句中的文件句柄和参数之间放了一个逗号。如果这样做,文件句柄将被视为参数。这似乎只适用于词法文件句柄。如果使用全局文件句柄,则会产生致命错误

No comma allowed after filehandle at ...

所以,要明确的是,如果您必须为print添加括号,请执行以下操作:

print($fh $stufftowrite)

虽然我个人更喜欢不使用括号,除非我必须这样做,因为它们只会增加混乱。

答案 2 :(得分:8)

现代Perl书籍在Chapter 11("要避免什么"),"间接符号标量限制":

中说明
  

语法的另一个危险是解析器需要单个标量表达式作为对象。打印到存储在聚合变量中的文件句柄似乎很明显,但它不是:

# DOES NOT WORK AS WRITTEN
say $config->{output} 'Fun diagnostic message!';
  

Perl将尝试在$ config对象上调用say。   printclosesay - 所有以文件句柄操作的内置函数 - 以间接方式运行。当文件句柄是包全局变量时,这很好,但是词法文件句柄(Filehandle References)使间接对象语法问题变得明显。要解决此问题,请消除产生预期调用的子表达式的歧义:

say {$config->{output}} 'Fun diagnostic message!';

当然,print({$fh} $stufftowrite)也是可能的。

答案 3 :(得分:3)

如何定义print的语法。它真的那么简单。有什么可以解决的。如果在文件句柄和其余参数之间放置逗号,则表达式将解析为print LIST而不是print FILEHANDLE LIST。是的,这看起来很奇怪。 非常奇怪。

不被解析为print LIST的方法是提供一个可以合法解析为print FILEHANDLE LIST的表达式。如果你要做的是围绕print的参数括起来使它看起来更像普通的函数调用,你可以说

print($fh $stufftowrite); # note the lack of comma

你也可以说

(print $fh $stufftowrite);

如果您尝试执行的操作是从周围代码中设置print表达式。关键是包括逗号会改变解析。