2011-10-14 82 views
1

我有兩個嵌套的foreach循環。如果我用這個代碼:<DATA>防止執行foreach循環,爲什麼? :)

foreach (@directories) { 
    my $actual_directory = $_; 
    print "\nactual directory: ".$actual_directory."\n"; 

    foreach (@files) { 
     my $file_name = $_; 
     my $actual_file = $actual_directory.$file_name; 
     print $actual_file."\n"; 

     open(DATA, $actual_file) or die "Nelze otevřít zdrojový soubor: $!\n"; 
     my $line_number = 0; 

     # while (<DATA>){ 
     #  my @znaky = split(' ',$_); 
     #  my $poradi = $znaky[0]; #poradi nukleotidu 
     #  my $hodnota = $znaky[1]; #hodnota 

     #  my @temp = $files_to_sum_of_lines{$actual_file}; 
     #  $temp[$line_number] += $hodnota;  
     #  $files_to_sum_of_lines{$actual_file} = @temp; 

     #  $line_number+=1; 
     # } 
     # close(DATA); 
    } 
} 

我得到這樣的輸出:

actual directory: /home/n/Plocha/counting_files/1/ 

/home/n/Plocha/counting_files/1/a.txt 
/home/n/Plocha/counting_files/1/b.txt 

actual directory: /home/n/Plocha/counting_files/2/ 

/home/n/Plocha/counting_files/2/a.txt 
/home/n/Plocha/counting_files/2/b.txt 

但是,如果我去掉「while (<DATA>){ }」,我失去A.TXT和b.txt,因此輸出看起來是這樣的:

actual directory: /home/n/Plocha/counting_files/1/ 

/home/n/Plocha/counting_files/1/a.txt 
/home/n/Plocha/counting_files/1/b.txt 

actual directory: /home/n/Plocha/counting_files/2/ 

/home/n/Plocha/counting_files/2/ 
/home/n/Plocha/counting_files/2/ 

這怎麼while (<DATA>)阻止我的foreach被執行? 任何幫助將不勝感激。非常感謝。

回答

3

Perl使用__DATA__在軟件包末尾生成一個僞數據文件。您可以使用文件句柄DATA訪問該文件,例如, <DATA>。你的文件句柄可能是衝突的嗎?嘗試將文件句柄更改爲其他內容,並查看它是否更好。

7

除了不使用DATA,請嘗試使用詞法循環變量和詞法文件句柄。另外,Perl的內置$.會記錄您的行號。

for my $actual_directory (@directories) { 
    print "\nactual directory: ".$actual_directory."\n"; 

    foreach my $file_name (@files) { 
     my $actual_file = $actual_directory.$file_name; 
     print $actual_file."\n"; 

     open my $INPUT, '<', $actual_file 
      or die "Nelze otevřít zdrojový soubor: $!\n"; 

     while (my $line = <$INPUT>) { 
       my @znaky = split(' ', $line); 
       my $poradi = $znaky[0]; #poradi nukleotidu 
       my $hodnota = $znaky[1]; #hodnota 
       @temp = $files_to_sum_of_lines{$actual_file}; 
       $temp[ $. ] += $hodnota; 
       $files_to_sum_of_lines{$actual_file} = @temp; 
     } 
     close $INPUT; 
    } 
} 

另一方面,我不能確定那裏是否有邏輯錯誤。類似以下內容可能會有用:

#!/usr/bin/perl 

use warnings; use strict; 

use Carp; 
use File::Find; 
use File::Spec::Functions qw(catfile canonpath); 

my %counts; 
find(\&count_lines_in_files, @ARGV); 

for my $dir (sort keys %counts) { 
    print "$dir\n"; 
    my $dircounts = $counts{ $dir }; 
    for my $file (sort keys %{ $dircounts }) { 
     printf "\t%s: %d\n", $file, $dircounts->{ $file }; 
    } 
} 

sub count_lines_in_files { 
    my $file = canonpath $_; 
    my $dir = canonpath $File::Find::dir; 
    my $path = canonpath $File::Find::name; 

    return unless -f $path; 

    $counts{ $dir }{ $file } = count_lines_in_file($path); 
} 

sub count_lines_in_file { 
    my ($path) = @_; 

    my $ret = open my $fh, '<', $path; 

    unless ($ret) { 
     carp "Cannot open '$path': $!"; 
     return; 
    } 
    1 while <$fh>; 

    my $n_lines = $.; 

    close $fh 
     or croak "Cannot close '$path': $!"; 

    return $n_lines; 
} 
+1

看來,當$ _在while循環中被覆蓋時,它也正在更改文件數組。因爲直到$ _是undef,在目錄循環的下一次迭代中,@files僅包含undefs:D – vmpstr

+2

@Sinan,typo - 我認爲你的意思是'while <$DATA>'引用你的詞法fh而不是內置DATA句柄。當命名一個文件句柄時,最好避免使用任何{DATA}命令:) – pilcrow

+0

非常感謝,它的工作原理和確實更清晰的解決方案:) – Perlnika