Perl добавление массива в таблицу ha sh - PullRequest
1 голос
/ 19 марта 2020

При чтении массива (фактически массива массивов) из таблицы ha sh, кажется, что в структуре данных есть дополнительный уровень. Я заполняю массив из файла как таковой.

open(my $fh, '<', $newfile) or next; 
while (my $line = <$fh>)  
{ 
    my @job = split /\s+/, $line;
    push @userjobs, [ @job ];               
}
close ($fh);

userjobs имеет размер три, как и ожидалось, из файла, и добавляю его в% crontab ha sh

$crontab{$user} = [ @userjobs ];

Когда я пытаюсь прочитать задание пользователя обратно, его размер равен 1

my @temp = $crontab{$user};

Глядя на Dumper, можно увидеть дополнительный уровень в иерархии табличных значений ha sh. Я могу получить доступ к таблице ha sh через что-то вроде $ crontab {$ user} [0] [0]. Тем не менее, теперь я хочу добавить 4-й пользовательский проект, но не могу получить доступ к базовому массиву заданий. Добавление push @temp, [ @newjob ] добавляет его к дополнительному уровню, но не к массиву заданий. Есть идеи, что я делаю не так?

Ответы [ 4 ]

3 голосов
/ 19 марта 2020

Вы добавляете массив ссылка к ха sh:

$crontab{$user} = [ @userjobs ];

Если вы хотите получить доступ к массиву, вам нужно разыменовать это :

my @temp = @{ $crontab{$user} };

Обратите внимание, что эта техника потенциально подразумевает копию ha sh. Это может быть более эффективно сделать:

$crontab{$user} = \@userjobs;
2 голосов
/ 19 марта 2020

Значением элементов ha sh являются скаляры, поэтому $crontab{$user} является скаляром (содержащим ссылку на массив), поэтому присваивается один скаляр @temp. Заменить

my @temp = $crontab{$user};

print(Dumper(\@temp));

for (@temp) { ... }

на

my $temp = $crontab{$user};

print(Dumper($temp));

for (@$temp) { ... }
2 голосов
/ 19 марта 2020

Вопрос не очень ясен относительно желаемой структуры %crontab га sh.

Следующий фрагмент кода основан на лучшем предположении, что %crontab га sh будет иметь имя пользователя в качестве ключа, а задания будут храниться в массиве, на который ссылается значение, связанное с ключом (именем пользователя).

ПРИМЕЧАНИЕ: изменить $debug = 1 для просмотра %crontab га sh структура

use strict;
use warnings;
use feature 'say';

use Data::Dumper;

my $debug = 0;

my %crontab;

while(<DATA>) {
    my($user,@jobs) = split '\s+';

    push @{$crontab{$user}}, @jobs;
}

say Dumper(\%crontab) if $debug;

while( my($k,$v) = each %crontab ) {
    say 'User: ' . $k . ' => ' . join ' ', @{$v};
}

__DATA__
user1 job1 job2 job3
user2 job1 job2 job3 job4 job5
user3 job1 job2 job3 job4
user4 job1
1 голос
/ 19 марта 2020

Хех, думаю, я только что ответил на похожую проблему в Как напечатать значения ссылки на массив в perl? . Вы назначаете ссылку на массив для именованного массива. Поскольку ссылка является скаляром (одно значение), вы получаете массив из одного значения, которое является ссылкой. Теперь у вас есть массив массивов:

my @temp = $array_reference; # likely wrong.

Это то же самое, что создать список из одного элемента и присвоить его @temp:

my @temp = ( [ ... ] );

Вот где ваш дополнительный уровень приходит. Первый уровень для @temp. Вы получаете доступ к $temp[0], чтобы перейти к первому элементу в массиве, который является ссылкой. Теперь вам нужно перейти к элементам в этой ссылке, так что это ваш второй уровень: $temp[0][0].

Поскольку все ссылки являются скалярами, вы, вероятно, хотели назначить скаляр:

my $temp = $array_reference;

Теперь это просто ссылка без дополнительной обертки массива, так что вы можете получить доступ к его первому элементу как $temp[0]. Поскольку все значения ha sh являются скалярами, возможно, вы захотите присвоить его:

my $temp = $crontab{$user};     # whole ref
my $first = $crontab{$user}[0]; # just first element
...