所以我试图用以下代码做的是推送一个字符串,让我们在散列中的每个键的末尾说“this string”。我完全不知道如何做到这一点。这是我的代码:
use warnings;
use strict;
use File::Find;
my @name;
my $filename;
my $line;
my @severity = ();
my @files;
my @info = ();
my $key;
my %hoa;
my $xmlfile;
my $comment;
my @comments;
open( OUTPUT, "> $ARGV[0]" );
my $dir = 'c:/programs/TEST/Test';
while ( defined( $input = glob( $dir . "\\*.txt" ) ) ) {
open( INPUT, "< $input" );
while (<INPUT>) {
chomp;
if (/File/) {
my @line = split /:/;
$key = $line[1];
push @{ $hoa{$key} }, "Filename\n";
}
if ( /XML/ ... /File/ ) {
$xmlfile = $1;
push @{ $hoa{$key} }, "XML file is $xmlfile\n";
}
if (/Important/) {
push @{ $hoa{$key} }, "Severity is $_\n";
}
if (/^\D/) {
next if /Important/;
push @{ $hoa{$key} }, "Given comment is $_\n";
}
push @{ $hoa{$key} }, "this string\n";
}
}
foreach my $k ( keys %hoa ) {
my @list = @{ $hoa{$k} };
foreach my $l (@list) {
print OUTPUT $l, "\n";
}
}
}
close INPUT;
close OUTPUT;
我有“这个字符串”是我试图将该字符串推送到数组末尾的地方。然而,最终发生的事情是它最终打印了“这个字符串”三次,而不是像我想要的那样在每个键的末尾打印。当我试图把它放在while()循环之外时,它说$ key的值没有被初始化。所以,请帮忙吗?如果您需要澄清我的要求,请告诉我。谢谢!
答案 0 :(得分:3)
没有冒犯,但是这段代码中有很多问题,我甚至不知道从哪里开始......
首先,Perl中不需要'初始化块'(此脚本开头的所有这些my $something; my @somethings
行)。事实上,它不仅仅是“多余的” - 它实际上令人困惑:每次遇到一个新变量时我都必须来回移动我的焦点来检查它的类型。此外,即使所有这些$input
var仍未被声明为本地;它或者在评论中缺失,或者给出的代码有遗漏。
其次,为什么宣布你打算使用File :: Find(好) - 但是根本不使用它?它可以大大简化所有while(glob) { while(<FH>) { ... } }
例程。
第三,我不确定为什么只有当行读取与/ File /匹配时才向$key
分配内容,但在其他所有情况下都将其值用作键。这是尝试读取按部分组织的文件吗?然后可以通过slurp / splitting或本地化$/
变量来更简单地完成...
无论如何,重点是如果扫描的文件的第一行与/File/
不匹配,则使用前一个(即,来自前一个文件!)的值 - 我不太确定它的目的。如果第一个文件的第一行不是/File/
- 匹配,那么一个空字符串被用作键 - 再次,它闻起来像一个bug ...
您能否详细描述一下您的任务?给出一些测试输入/输出结果,或许......继续执行简短任务,组织代码进行处理会很棒。
答案 1 :(得分:3)
你的程序设计不合理,打破了很多良好做法规则。而不是全部枚举它们,这是一个具有更好结构的等效程序。
我想知道您是否知道{em>所有的if
语句都会被测试并可能被执行?也许您需要使用elsif
?
除了在使用$ key时未定义$ key的可能性之外,您还将$xmlfile
设置为$1
,永远将被定义为没有捕获任何正则表达式。
无法从你的代码中判断出你想要做什么,所以只有当你向我们展示你的输出,输入并说出如何从另一个中推导出来时,我们才能帮助你。
use strict;
use warnings;
use File::Find;
my ($outfile) = @ARGV;
my $dir = 'c:/programs/TEST/Test';
my %hoa;
my $key;
while (my $input = glob "$dir/*.txt") {
open my $in, '<', $input or die $!;
while (<$in>) {
chomp;
if (/File/) {
my $key = (split /:/)[1];
push @{ $hoa{$key} }, "Filename\n";
}
if (/XML/ ... /File/) {
my $xmlfile = $1;
push @{ $hoa{$key} }, "XML file is $xmlfile\n";
}
if (/Important/) {
push @{ $hoa{$key} }, "Severity is $_\n";
}
if (/^\D/) {
next if /Important/;
push @{ $hoa{$key} }, "Given comment is $_\n";
}
push @{ $hoa{$key} }, "this string\n";
}
close $in;
}
open my $out, '>', $outfile or die $!;
foreach my $k (keys %hoa) {
foreach my $l (@{ $hoa{$k} }) {
print $out $l, "\n";
}
}
close $out;
答案 2 :(得分:1)
我怀疑基于你的代码,每次循环都没有调用设置$ key的行,并且你不会触发任何其他if语句。
这会将“this string”追加到数组的末尾。基于你在数组的末尾得到3个“this strings”,我怀疑两行不通过if(/ FILE /)或任何其他if语句。这将使$ key值保持不变,最后,您将使用$ key的最后一个值设置时将“this string”追加到数组中。
答案 3 :(得分:1)
这会将字符串"this string"
附加到散列%hoa
的每个元素,这些元素是数组引用:
for (values(%hoa)) { push @{$_}, "this string"; }
将它放在while循环之外,然后在%hoa
的每个元素的末尾打印“this string”。
它将自动生成数组引用,它会找到undef
元素。如果它不能将元素作为数组取消引用,它也会阻塞,并且如果它找到一个简单的标量并且不在严格下运行,它将通过符号引用来操作数组。
my %autoviv = ( a => ['foo'], b => undef );
push @$_, "PUSH" for values %autoviv; # ( a => ['foo', 'PUSH'], b => ['PUSH'] )
my %fatal = ( a => {} );
push @$_, "PUSH" for values %fatal; # FATAL: "Not an ARRAY reference at..."
my %dangerous = (a => "foo");
push @$_, "PUSH" for values %dangerous; # Yikes! @foo is now ("PUSH")
use strict;
my %kablam = (a => "foo");
push @$_, "PUSH" for values %kablam; # "Can't use string ("foo") as an ARRAY ref ..."
答案 4 :(得分:0)
据我了解,使用map
命令遍历散列以修改其密钥。一个例子:
编辑:我编辑过,因为我意识到map
命令可以分配给同一个哈希。无需创建新的。
#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;
my %hash = qw|
key1 value1
key2 value2
key3 value3
|;
my %hash = map { $_ . "this string" => $hash{ $_ } } keys %hash;
print Dump \%hash;
像以下一样运行:
perl script.pl
使用以下输出:
$VAR1 = {
'key3this string' => 'value3',
'key2this string' => 'value2',
'key1this string' => 'value1'
};