2017-04-18 108 views
1

我试图创建一个脚本,它将从模板中生成perl代码,并且我无法理解所引发的错误以及为什么我的解决方法修复了它。如何打印在here-doc中嵌入的代码为词法文件句柄

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

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. 

本来这个脚本只是打印到stdout,而不是写入文件 - 没有错误抛出。在添加文件处理和接收这个错误之后,我然后试图使用一个裸文件句柄 - 再次没有错误抛出。

所以,如果我只是将“$ fh”替换为“FH”,那么脚本将按预期工作。关于词法文件句柄导致它窒息的是什么?

+0

尝试使用IO :: Handle和$ fh-> print()语法。 – AKHolland

+1

另一个解决方法...'print {$ fh} <<“MODULE”;''参考'perldoc -f print' – toolic

+0

@AKHolland:方便地,'IO :: File'(以及IO :: Handle')根据需要由任何Perl v5.14或更高版本加载。这意味着你可以使用任何文件句柄,就好像它是一个'IO :: File'对象,而不事先添加显式的'use IO :: File'。 – Borodin

回答

1

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

print $fh << "MODULE"; 

具体语法歧义时,<<可以是向左移位运算符或这里-DOC的开始。


有两条路径可以解决该问题。

  • 可以消除不确定性:

    print $fh +<< "MODULE"; 
    

    print $fh (<< "MODULE"); 
    

    print { $fh } << "MODULE"; 
    

    $fh->print(<< "MODULE"); 
    
  • 你就可以欺骗perl到正确猜测:

    print $fh <<"MODULE"; 
    

注意print $fh +<< "MODULE";引入备用歧义。 +是二元还是一元+运算符?谢天谢地,它根据需要被解释为一元 - +


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

+0

我认为通过假定左移操作解决了歧义性,当其中一个操作数是字面非数字string_时,这似乎很奇怪。即使'use warnings' pragma知道''MODULE''是'<<'的一个无效参数(尽管编译器检查对于解析语义来说太迟了) – ardnew

2

应该没有空间标识后<< here文档,所以

print $fh << "MODULE"; 

应该

print $fh <<"MODULE"; 

或更加整齐

print $fh <<MODULE; 

或许

print $fh (<< "MODULE"); 

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

+0

'perldoc perlop':“<<和标识符之间可能没有空格,除非该标识符是明确引用的。” OP使用明确的引号。 – toolic

+1

@toolic:我想这只是错误的。我将提交一个错误报告 – Borodin

+0

,同时在错误报告中还记得,这种行为仅在使用词法文件句柄时才会发生,它比'<<'运算符周围的间距更具体。并感谢您的洞察力! – ardnew