<数据>阻止 foreach 循环执行,为什么? :)

发布于 2024-12-09 14:03:48 字数 1621 浏览 1 评论 0原文

我有两个嵌套的 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 (){ }”,我会丢失 a.txt 和 b.txt,因此输出看起来像this:

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 () 如何阻止我的 foreach 被执行? 任何帮助将不胜感激。多谢。

I have two nested foreach loops. If I use this code:

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); 
    }
} 

I got this output:

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

However, if I uncomment "while (<DATA>){ }", I loose a.txt and b.txt, so the output looks like this:

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/

How can this while (<DATA>) prevent my foreach from being executed?
Any help will be appreciated. Thanks a lot.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

你丑哭了我 2024-12-16 14:03:48

除了不使用 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;
}

In addition to not using DATA, try using lexical loop variables, and lexical filehandles. Also, Perl's built-in $. keeps track of line numbers for you.

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; 
    }
}

On the other hand, I can't quite tell if there is a logic error in there. Something like the following might be useful:

#!/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;
}
治碍 2024-12-16 14:03:48

Perl 使用 __DATA__ 制作伪数据文件在包裹的最后。您可以使用文件句柄 DATA 访问该文件,例如 ;。您的文件句柄可能有冲突吗?尝试将文件句柄更改为其他内容,看看是否效果更好。

Perl uses __DATA__ to make a pseudo-data file at the end of the package. You can access that using the filehandle DATA, e.g. <DATA>. Is it possible that your filehandle is conflicting? Try changing the filehandle to something else and see if it works better.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文