<DATA> препятствует выполнению цикла foreach, почему?:) - PullRequest
1 голос
/ 14 октября 2011

У меня есть два вложенных цикла 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? Любая помощь будет оценена. Большое спасибо.

Ответы [ 2 ]

7 голосов
/ 14 октября 2011

В дополнение к неиспользованию 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;
}
3 голосов
/ 14 октября 2011

Perl использует __DATA__ для создания файла псевдоданных в конце пакета. Вы можете получить к нему доступ, используя файловый дескриптор DATA, например, <DATA>. Возможно ли, что ваш файловый дескриптор конфликтует? Попробуйте изменить дескриптор файла на что-то другое и посмотрите, работает ли он лучше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...