如何将嵌入在 here-doc 中的代码打印到词法文件句柄

How to print code embedded in a here-doc to lexical filehandle

我正在尝试创建一个将从模板生成 perl 代码的脚本,但我无法理解抛出的错误以及我的变通方法修复它的原因。

这个例子是人为设计的,但它说明了问题:

use strict;
use warnings;

my $name = shift; # from @ARGV
my $file = sprintf "%s.pm", $name;

open my $fh, ">", $file
  or die "error: open(>, '$file'): $!";

print $fh << "MODULE";
package $name;

#
# blah blah
#

use strict;
use warnings;

require Exporter;

our \@ISA       = qw| Exporter |;
our \@EXPORT    = qw| |; # automatic exports
our \@EXPORT_OK = qw| |; # on-demand exports

# CODE

1;
MODULE

close $fh;

当运行这个脚本时,我得到以下错误:

$ perl script.pl Foo
Invalid version format (non-numeric data) at script.pl line 11, near "package "
syntax error at script.pl line 11, near "package $name"
BEGIN not safe after errors--compilation aborted at script.pl line 17.

最初这个脚本只是打印到标准输出而不是写入文件 -- 没有抛出错误。添加文件处理并收到此错误后,我尝试只使用一个裸文件句柄——再次没有抛出任何错误。

因此,如果我只是在所有地方用 "FH" 替换“$fh”,脚本就会按预期工作。导致此阻塞的词法文件句柄是什么?

标记here文档<<后应该没有space,所以

print $fh << "MODULE";

应该是

print $fh <<"MODULE";

或更整齐

print $fh <<MODULE;

或者也许

print $fh (<< "MODULE");

因为 << 被视为左移运算符,Perl 继续尝试编译 package 语句。找不到有效的包名称,它尝试使用 $name 作为版本号,并抱怨因为它不是一个

Perl 是一种有歧义的语言。这意味着并不总是很清楚应该如何解析它。在某些情况下,perl 必须猜测如何解析某些内容。

中存在语法歧义
print $fh << "MODULE";

具体来说,<< 可以是左移运算符或 here-doc 的开头。


您可以通过两种途径解决该问题。

  • 可以消除歧义:

    print $fh +<< "MODULE";
    

    print $fh (<< "MODULE");
    

    print { $fh } << "MODULE";
    

    $fh->print(<< "MODULE");
    
  • 你可以欺骗 perl 猜对:

    print $fh <<"MODULE";
    

请注意,print $fh +<< "MODULE"; 引入了另一种歧义。 + 是二元还是一元 + 运算符?值得庆幸的是,它根据需要被解释为一元-+


顺便说一句,<<"MODULE"可以缩短为<<MODULE