目的:
我正在尝试计算文本文件中“column”20中的值,然后使用文本文件中该行的值打印出现次数。一些行将是相同的,“列”0(第一列)除外。我试图使用哈希(虽然我对如何使用哈希的理解有限)。
问题:
在子函数中执行 push (在foreach循环内)时,该值不会被推送到循环外的数组,因此输出将不会保存到文件中。在循环内部打印工作(打印 $ dummy )并显示所有数据。
INPUT:
Filename1 Value1a Value2a Value3a ... Column20a ... ColumnENDa
Filename2 Value1b Value2b Value3b ... Column20b ... ColumnENDb
Filename3 Value1c Value2c Value3c ... Column20a ... ColumnENDc
...
OUTPUT(使用print $ dummy 内部循环):
2 Column20a Filename1, Filename3
1 Column20b Filename2
...
CODE:
use strict;
use warnings;
use Cwd;
use File::Find::Rule;
use File::Spec;
use File::Basename;
use Text::Template;
use File::Slurp;
use List::MoreUtils qw(uniq);
my $current_dir = cwd;
my @test_file = read_file ("test_file.txt");
my %count = ();
my %name = ();
my @test = "Counts\tName\tFile_names";
foreach (@test_file) {
chomp $_;
our(@F) = split('\t', $_, 0);
++$count{"$F[20] "};
$name{"$F[20] "} .= "$F[0]," if $F[20];
sub END {
foreach $_ (keys %name) {
$name{$_} =~ s/,$//;
my $dummy = "$count{$_}\t $_\t $name{$_}\n";
#print $dummy;
push (@test, $dummy);
}
};
}
print "@test";
write_file( 'test.txt', @test);
为什么push函数不能在sub(foreach循环)之外工作?
答案 0 :(得分:1)
你实际上并没有打电话给你。
如果你认为它是END
block,它不应该是一个子 - 你不应该使用END块,除非有技术上的理由这样做。
如果你的意思是它是一个sub,请将其命名为实际上称之为(名称不是错误,只是看起来很糟糕 - END
具有特殊意义)。
代码的结尾将是(不修复/改进它):
foreach (@test_file) {
chomp $_;
our(@F) = split('\t', $_, 0);
++$count{$F[20]};
$name{$F[20]} .= "$F[0]," if $F[20];
}
process_test();
print "@test";
write_file( 'test.txt', @test);
##########################
sub process_test {
foreach $_ (keys %name) {
$name{$_} =~ s/,$//;
my $dummy = "$count{$_}\t $_\t $name{$_}\n";
push (@test, $dummy);
}
}
作为替代方案,甚至没有子代码(对于几行代码不是必需的):
foreach (@test_file) {
chomp $_;
our(@F) = split('\t', $_, 0);
++$count{$F[20]};
$name{$F[20]} .= "$F[0]," if $F[20];
}
foreach $_ (keys %name) {
$name{$_} =~ s/,$//;
my $dummy = "$count{$_}\t $_\t $name{$_}\n";
push (@test, $dummy);
}
print "@test";
write_file('test.txt', @test);
我在我自己的代码版本上对此进行了测试,并使用您的测试输入在输出文件中获得以下内容:
Counts Name File_names
2 Column20a Filename1,Filename3
1 Column20b Filename2
答案 1 :(得分:0)
为什么要在foreach循环中编写子程序?因此,对于循环中的每次迭代,您都会创建一个新的循环。 您的子程序名称也存在问题。其实你不打电话。你不能调用它,因为perl使用END作为END块。让我用一个例子告诉你:
use warnings;
use strict;
END('hello world');
sub END{
my $string = shift;
print $string;
}
END块的目的是在程序结束时执行括号之间的所有操作,因此命名为。
use warnings;
use strict;
END('hello world');
sub END{
my $string = shift;
print $string;
}
要么省略子程序,要么在全局上下文中声明它,例如在课程结束时。