我想通过从以->分隔的多维数组中读取值来创建嵌套哈希。
Array 1: key1->key2->key3->value
Array 2: key1->key2->value
Array 3: key1->value
当键具有值和子键时,例如key2具有值,另一个key3也具有值,然后得到错误“不是HASH引用”。似乎它正在覆盖先前的哈希并考虑使用它的数组。
我们非常感谢您的帮助。我尝试使用转储程序模块调试和打印变量的值以及输出,并发现它是ARRAY参考,而不是哈希。
为了进行复制,请创建.txt文件,例如从1到3.txt在任何文件夹中,并且在这些文件中具有以下内容1.txt:/ TEST-TAG = ABC-> DEF-> fma-> GHI / 2.txt:/ * TEST -TAG = ABC-> DEF-> fma 3.txt:/ * TEST-TAG = ABC-> DEF,然后在perl脚本中包含
#!/usr/bin/perl
use strict;
use warnings;
my @lines=`grep -R 'TEST-TAG =' <FOLDER where .txt files present>`;
my $hash;
#parse the lines which has pattern /\*TEST-TAG = ABC->DEF->fma->GHI\*/
foreach (@lines)
{
print "line is $_\n";
my($all_cat) = $_ =~ /\=(.*)\*\//;
print "all cat is $all_cat\n";
my($testname) = $_ =~ /\/.*\/(.*)\./;
print "testname is $testname\n";
if (!$all_cat eq "") {
$all_cat =~ s/ //g;
my @ts = split(',', $all_cat);
print "ts is @ts\n";
my $i;
foreach (@ts) {
my @allfeat = split('->',$_);
my $count = scalar @allfeat;
for ($i = 0; $i<$count; $i++) {
my @temparr = @allfeat[$i..$count-1];
print "temparr is @temparr\n";
push @temparr, $testname;
ToNestedHash($hash, @temparr);
}
}
}
}
sub ToNestedHash {
my $ref = \shift;
print "sandeep in ref $ref\n";
print "sandeep in ref", ref($ref), "\n";
my $h = $$ref;
print "sandeep h $h\n";
my $value = pop;
print "sandeep value is $value\n";
print "sandeep array is @_\n";
print "refrence", ref($h), "\n";
foreach my $i (@_) {
print " before INDEX $i\n";
print Dumper($ref);
$ref =\$$ref->{ $i };
print "after INDEX $i\n";
print Dumper($ref);
}
if (!isinlist(\@{$$ref},$value)) {
push @{$$ref}, $value;
}
return $h;
}
# If element exists in the list
sub isinlist {
my ($aref, $key) = ($_[0], $_[1]);
foreach my $elem (@$aref){
if ($elem eq $key) {
return 1;
}
}
return 0;
}
我得到带有调试打印的输出
line is File.txt:/*TEST-TAG = ABC->DEF->fma->GHI*/
all cat is ABC->DEF->fma->GHI
testname is hmma_884_row_row_f16_f16
ts is ABC->DEF->fma->GHI
temparr is ABC DEF fma GHI
sandeep in ref REF(0x12a1048)
sandeep in refREF
sandeep h HASH(0x12a09a0)
sandeep value is hmma_884_row_row_f16_f16
sandeep array is ABC DEF fma GHI
refrenceHASH
REF
temparr is DEF fma GHI
sandeep in ref REF(0x12a1048)
sandeep in refREF
sandeep h HASH(0x12a09a0)
sandeep value is hmma_884_row_row_f16_f16
sandeep array is DEF fma GHI
refrenceHASH
REF
temparr is fma GHI
sandeep in ref REF(0x12a1048)
sandeep in refREF
sandeep h HASH(0x12a09a0)
sandeep value is hmma_884_row_row_f16_f16
sandeep array is fma GHI
refrenceHASH
Not a HASH reference at createjson.pl line 80.
问题行是$ref =\$$ref->{$_} foreach (@_);
答案 0 :(得分:2)
睡了之后,我意识到您想在哪里继续尝试下去。您关心的问题是您试图将某些哈希值既用作数组又用作哈希。有两种解决方法。检测并处理它,或者避免它。避免代码更加简洁,因此我将对其进行演示。
正如我在原始答案中提到的那样,我不确定您对'Dumper'行的想法是什么,但是Data :: Dump可能是您正在使用的内容的有用替代品,其复杂度小于Data :: Dumper模块,我当时以为您正在设法使用它。我还选择仍然为您的文件名regex替换,因为我仍然不想打扰完整的路径名。
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dump;
my @lines = `grep -R 'TEST-TAG =' foo`;
my $hash;
$| = 1; # keep STDOUT and STDERR together
#parse the lines which has pattern /\*TEST-TAG = ABC->DEF->fma->GHI\*/
foreach (@lines) {
print "line is $_\n";
my($all_cat) = $_ =~ /\=(.*)\*\//;
print "all cat is $all_cat\n";
my($testname) = $_ =~ /(?:.*\/)?(.*?)\./;
print "testname is $testname\n";
if ($all_cat ne "") {
$all_cat =~ s/ //g;
my @ts = split(',', $all_cat);
print "ts is @ts\n";
my $i;
foreach (@ts) {
my @allfeat = split('->',$_);
my $count = scalar @allfeat;
for ($i = 0; $i<$count; $i++) {
my @temparr = @allfeat[$i..$count-1];
print "temparr is @temparr\n";
push @temparr, $testname;
ToNestedHash($hash, @temparr);
}
}
}
}
sub ToNestedHash {
my $ref = \shift;
print "sandeep in ref ";
dd $ref;
my $h = $$ref;
print "sandeep h ";
dd $h;
my $value = pop;
print "sandeep value is $value\n";
print "sandeep array is @_\n";
print "refrence", ref($h), "\n";
foreach my $i (@_) {
print " before INDEX $i\n";
dd $ref;
$ref =\$$ref->{ $i };
print "after INDEX $i\n";
dd $ref;
}
$ref =\$$ref->{ _ARRAY };
if (!isinlist(\@{$$ref},$value)) {
push @{$$ref}, $value;
}
return $h;
}
# If element exists in the list
sub isinlist {
my ($aref, $key) = ($_[0], $_[1]);
foreach my $elem (@$aref){
if ($elem eq $key) {
return 1;
}
}
return 0;
}