2011-04-03 16 views
1

我一直試圖擺脫一個奇怪的錯誤數小時,沒有成功。我有一個排序文件的子程序。這裏是代碼:perl創建不明原因的文件,名爲「1」

sub sort_file { 
    $filename = @_; 

    print @_; 
    print $filename; 

    open(SRTINFILE,"<$filename"); 
    @lines=<SRTINFILE>; 
    close(SRTINFILE); 

    open(SRTOUTFILE,">$filename"); 
    @sorted = sort { @aa=split(/ /,$a); @bb=split(/ /,$b); return ($aa[1] <=> $bb[1]); } @lines; 
    print SRTOUTFILE @sorted; 

    close(SRTOUTFILE); 

} 

任何時候這個函數運行時,perl會創建一個叫做「1」的文件。我不知道爲什麼。我是一個完整的perl noob,我只是用它來快速和骯髒的文本文件處理。任何人都知道什麼是錯的?

回答

2

其他答案足以告訴你爲什麼你得到奇怪的錯誤。

我想告訴你一個更有經驗的Perl程序員如何編寫這個子程序。

use warnings; 
use strict; 
use autodie; 

sub sort_file { 
    my($filename) = @_; 

    my @lines; 
    { 
    # 3 arg open 
    open my $in_fh, '<', $filename; 
    @lines = <$in_fh>; 
    close $in_fh; 
    } 

    # Schwartzian transform 
    my @sorted = map{ 
    $_->[0] 
    } sort { 
    $a->[2] <=> $b->[2] 
    } map { 
    [ $_, split ' ', $_ ] 
    } @lines; 

    { 
    open my $out_fh, '>', $filename; 
    print {$out_fh} @sorted; 
    close $out_fh; 
    } 
} 
  • use strict;
    防止您使用的變量,而不宣告它(除其他外)。

  • use warnings;
    通知您一些潛在的錯誤。

  • use autodie;
    現在你不需要寫open .... or die ....

  • { open ...; @lines = <$fh>; close $fh }
    限制文件句柄的範圍。

  • @sorted = map { ... } sort { ... } map { ... } @list
    這是一個Schwartzian transform,這降低了這些值被分割的次數的示例。在這個例子中,它可能是矯枉過正的。

-1

好的......沒關係。它剛剛在我身上閃現。 $filename = @_;是沒有意義的。應該是$filename = @_[0];。我的生活有兩個小時。注意其他perl noobs:注意。

+0

我的答案有一些選擇。 TMTOWTDI :) – mkb 2011-04-03 04:12:02

+3

請使用'use strict;使用警告;'在你的代碼中。它可以節省你的生命2個多小時。 – ikegami 2011-04-03 04:12:29

+0

哈哈。謝謝,mkb。我提交之前,我看到你的答案。採取的一點,perl似乎有很多方式做任何事情。我喜歡:D – dmitriy 2011-04-03 04:20:35

2

有多混淆。指定$filename = @_您的方式意味着您要在標量上下文中評估數組,這意味着$filename被分配了@_中的元素數。因爲您不檢查第一個open調用是否成功,所以讀取文件1可能會失敗,但您仍然繼續並打開編寫名爲1的文件。解決方法是在數組上下文中使用$filename,並使用($filename) = @_$filename = shift開始子例程。

爲什麼你不使用use strict的方式?

+1

「爲什麼你不使用嚴格的方式?回答:因爲當談到perl時,我是一個牛仔noob,他甚至還沒有讀過教程。感謝您的提示,只是添加了該行。 – dmitriy 2011-04-03 04:16:46

10

標量上下文中的數組將評估數組中元素的數量。如果將一個參數傳遞給該函數,則以下分配1$filename

$filename = @_; 

任何你想要的操作:

$filename = $_[0]; 
$filename = shift; 
($filename) = @_; 

此外,要限制變量的函數的範圍,所以你要

my $filename = $_[0]; 
my $filename = shift; 
my ($filename) = @_; 
(my $filename) = @_; # Exact same as previous. 
+1

...或者甚至是我的$ filename = shift' – 2011-04-03 04:18:35

+0

@Brad Gilbert,當然,但是如果你不打算用'@ _'做一些有趣的事情,爲什麼要使用較慢的'shift'。我會將它添加到「有趣」的答案中。 – ikegami 2011-04-03 04:19:51

+0

我不知道哪些perl版本,但(單)轉變過去更快(不是說這些微優化是重要的)。我想我看到PerlMonks上的基準測試,但大概是兩三年前。 – Ashley 2011-04-03 16:11:54

1

始終使用:

use strict; 
use warnings; 

然後Perl會告訴你什麼時候你不符合標準。

如你觀察到的,表示法:

$filename = @_; 

意味着無作用域變量被分配在參數列表中的功能元件的數量,並且由於傳遞一個文件,的名稱創建的文件將是'1'。

你的意思是寫:

my($filename) = @_; 

這提供了列表環境爲陣,並分配到$_[0]$filename,忽略任何額外的參數給函數。