Perl: не ссылка на HASH при создании вложенного хеша из многомерных массивов - PullRequest
0 голосов
/ 07 января 2019

Я хочу создать вложенный хеш, считывая значения из многомерных массивов, разделенных -> например,

Array 1: key1->key2->key3->value
Array 2: key1->key2->value
Array 3: key1->value

Когда ключ имеет значение и дополнительные ключи, например, key2 имеет значение и другой ключ key3, а затем выдает ошибку «Не ссылка на HASH». Кажется, он перезаписывает предыдущий хеш и рассматривает его как массив.

Помощь приветствуется. Я попытался отладить и распечатать значения переменных и вывод с помощью модуля dumper и увидеть, что это ссылка 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 (@_);

1 Ответ

0 голосов
/ 12 января 2019

После сна я понял, куда вы пытаетесь пойти с этим больше. Ваша проблема заключается в том, что вы пытаетесь использовать некоторые значения хеш-функций как в виде массивов, так и в качестве хеш-кодов. Есть два подхода к решению этой проблемы. Обнаружьте и обработайте это, или избегайте этого. Код избегания намного чище, поэтому я покажу это.

Как я упоминал в своем первоначальном ответе, я не уверен, что вы имели в виду для строк 'Dumper', но Data :: Dump, вероятно, является полезной заменой того, что вы использовали, с меньшими сложностями, чем Data Модуль Dumper, который, как я думал, вам каким-то образом удавалось использовать. Я также решил предоставить замену регулярному выражению имени файла, так как я все еще не хочу беспокоиться о полном пути.

#!/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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...