2017-04-18 107 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