2010-08-27 35 views
0

我寫在Perl comparefiles子程序從一個文件(f1)讀取文本行,然後在另一個(f2)正常O(n^2)方式搜索它。與文件處理工作在Perl

sub comparefiles { 
    my($f1, $f2) = @_; 
    while(<f1>) { 
     # reset f2 to the beginning of the file 
     while(<f2>) { 
     } 
    } 
} 

sub someother { 
    open (one, "<one.out"); 
    open (two, "<two.out"); 
    &comparefiles(&one, &two); 
} 

我有兩個問題

  • 我如何通過文件句柄的子程序?在上面的代碼中,我用它們作爲標量。那是正確的方法嗎?
  • 如何將文件指針f2重置爲上述註釋中標記位置的文件開頭?
+0

爲什麼不避免這個問題,並通過使用哈希使程序O(n)? – reinierpost 2010-08-27 12:31:21

+0

@reinierpost:我計劃稍後再做這些優化。 – Lazer 2010-08-27 13:19:27

回答

8

首先開始每一次與你的腳本:

use strict; 
use warnings; 

使用詞法文件句柄,三個參數打開和測試結果:

open my $fh1 , '<' , $filename1 or die "can't open '$filename1' for reading : $!"; 

然後,你可以通過文件句柄到sub:

comparefiles($fh1, $fh2); 

要倒回文件,請使用se EK功能(參閱perldoc -f搜索)

seek $fh, 0, 0; 
2

如果文件足夠小,以適應在內存中,你可能會考慮存儲在哈希線,這將避免對O(n^2)搜索的需求。

在你現有的方法的框架內,我建議不要嵌套你的文件閱讀循環 - 也許如果沒有其他的美學理由。相反,把內部循環放在一個子程序中。

use strict; 
use warnings; 

# Works for 2 or more files. 
analyze_files(@ARGV); 

sub analyze_files { 
    my @file_names = @_; 
    my @handles = map { open my $h, '<', $_; $h } @_; 
    my $fh = shift @handles; 

    while (my $line = <$fh>) { 
     my @line_numbers = map { find_in_file($_, $line) } @handles; 
     print join("\t", @line_numbers, $line); 
    } 
} 

# Takes a file handle and a line to hunt for. 
# Returns line number if the line is found. 
sub find_in_file { 
    my ($fh, $find_this) = @_; 
    seek $fh, 0, 0; 
    while (my $line = <$fh>){ 
     return $. if $line eq $find_this; 
    } 
    return -1; # Not found. 
}