Что означает то, когда Вы пытаетесь распечатать массив или хеш с помощью Perl, и Вы добираетесь, Массив (0xd3888)?

Что означает то, когда Вы пытаетесь распечатать массив или хеш, и Вы видите следующее; Массив (0xd3888) или ХЕШ (0xd3978)?

ПРИМЕР

КОД

my @data = (  
['1_TEST','1_T','1_TESTER'],  
['2_TEST','2_T','2_TESTER'],  
['3_TEST','3_T','3_TESTER'],  
['4_TEST','4_T','4_TESTER'],  
['5_TEST','5_T','5_TESTER'],  
['6_TEST','6_T','^_TESTER']  
);  

foreach my $line (@data) {  
   chomp($line);  
   @random = split(/\|/,$line);  
   print "".$random[0]."".$random[1]."".$random[2]."","\n";  
}  

РЕЗУЛЬТАТ

ARRAY(0xc1864)  
ARRAY(0xd384c)  
ARRAY(0xd3894)  
ARRAY(0xd38d0)  
ARRAY(0xd390c)  
ARRAY(0xd3948)  
13
задан Luke 18 May 2010 в 23:31
поделиться

3 ответа

Вы печатаете ссылку на хэш или массив, а не его содержимое.

В конкретном коде, который вы описываете, я припоминаю, что Perl автоматически превращает индексную переменную foreach цикла (my $line в вашем коде) в "псевдоним" (своего рода ссылку, я полагаю) значения на каждом этапе цикла.

Так $line является ссылкой на @data[x] ... который на каждой итерации является некоторым массивом. Чтобы получить один из элементов @data[0], потребуется сигил $ (поскольку элементы массива по адресу @data[0] являются скалярами). Однако $line[0] является ссылкой на какую-то пакетную/глобальную переменную, которой не существует (use warnings; use strict; скажет вам об этом, BTW).

[Отредактировано после того, как Ether указал на мое невежество] @data - это список анонимных ссылок на массивы, каждый из которых содержит список скаляров. Таким образом, вы должны использовать явную отсылку, которую я описываю ниже:

Что вам нужно, так это что-то вроде:

print ${$line}[0], ${$line}[1], ${$line}[2], "\n";

... обратите внимание, что ${xxx}[0] обеспечивает отсылку xxx, затем выполняется индексация результата отсылки, который затем извлекается как скаляр.

Я также тестирую это:

print $$line[0], $$line[1], $$line[2], "\n";

... и, кажется, это работает. (Однако я думаю, что первая форма более понятна, даже если она более многословна).

Лично я отношу это к очередному недоразумению в Perl.

[Дальнейшая редакция] Я все еще считаю это "попадаловом". Подобные вещи, а также тот факт, что большинство ответов на этот вопрос были технически правильными, но при этом совершенно не демонстрировали попыток помочь оригинальному автору, еще раз напомнили мне, почему я перешел на Python так много лет назад. Код, который я разместил, конечно, работает и, вероятно, выполняет то, что пытался сделать ОП. Мое объяснение было полностью неверным. Я увидел слово "псевдоним" на странице руководства `perlsyn` и вспомнил, что где-то там есть какая-то забавная семантика; поэтому я совершенно пропустил ту часть, что [...] создает анонимную ссылку. Если вы не пьете Perl Kool-Aid в глубоких черновиках, то даже самый простой код не может быть объяснен.
-2
ответ дан 1 December 2019 в 22:56
поделиться

Трудно сказать, имели вы это в виду или нет, но причина, по которой вы получаете ссылки на массив, заключается в том, что вы печатаете не то, что думаете.

Вы начали правильно, выполнив итерацию по "строкам" @data с:

foreach my $line (@data) { ... }

Однако следующая строка не работает. Похоже, что вы путаете текстовые строки со структурой массива. Да, каждая строка содержит строки, но Perl рассматривает @data как массив, а не как строку.

split используется для преобразования строк в массивы. Он не работает с массивами! То же самое относится и к chomp (за несущественным исключением).

Что вам нужно сделать, так это заменить содержимое цикла foreach на следующее:

foreach my $line (@data) {

    print $line->[0].", ".$line->[1].", ".$line->[2]."\n";
}

Вы заметите обозначение ->, которое здесь неспроста. $line ссылается на массив. Сам по себе он не является массивом. Стрелки -> отсылают к массиву, позволяя вам получить доступ к отдельным элементам массива, на который ссылается $line.

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

foreach my $line (@data) {

    my @random = @{ $line };
    print $random[0].", ".$random[1].", ".$random[2]."\n";
}

OUTPUT

1_TEST, 1_T, 1_TESTER
2_TEST, 2_T, 2_TESTER
3_TEST, 3_T, 3_TESTER
4_TEST, 4_T, 4_TESTER
5_TEST, 5_T, 5_TESTER
6_TEST, 6_T, ^_TESTER

Однострочный вариант может выглядеть примерно так print "@$_\n" for @data; (что немного нестандартно), но если вы хотите просто распечатать массив, чтобы посмотреть, как он выглядит (скажем, для отладки), я бы рекомендовал использовать модуль Data::Dump , который выводит массивы и хэши без лишних усилий.

Просто поместите use Data::Dump 'dump'; в начало вашего скрипта, а затем dump @data;. Вот так просто!

18
ответ дан 1 December 2019 в 22:56
поделиться

Это означает, что у вас нет массива; у вас есть ссылка на массив.

Обратите внимание, что массив указывается в круглых скобках - как список; когда вы используете обозначение квадратных скобок, вы создаете ссылку на массив.

foreach my $line (@data)
{
    my @array = @$line;
    print "$array[0] - $array[1] - $array[2]\n";
}

Иллюстрируя разницу:

my @data = (
['1_TEST','1_T','1_TESTER'],
['2_TEST','2_T','2_TESTER'],
['3_TEST','3_T','3_TESTER'],
['4_TEST','4_T','4_TESTER'],
['5_TEST','5_T','5_TESTER'],
['6_TEST','6_T','^_TESTER']
);

# Original print loop
foreach my $line (@data)
{
    chomp($line);
    @random = split(/\|/,$line);
    print "".$random[0]."".$random[1]."".$random[2]."","\n";
}

# Revised print loop
foreach my $line (@data)
{
    my @array = @$line;
    print "$array[0] - $array[1] - $array[2]\n";
}

Вывод

ARRAY(0x62c0f8)
ARRAY(0x649db8)
ARRAY(0x649980)
ARRAY(0x649e48)
ARRAY(0x649ec0)
ARRAY(0x649f38)
1_TEST - 1_T - 1_TESTER
2_TEST - 2_T - 2_TESTER
3_TEST - 3_T - 3_TESTER
4_TEST - 4_T - 4_TESTER
5_TEST - 5_T - 5_TESTER
6_TEST - 6_T - ^_TESTER
4
ответ дан 1 December 2019 в 22:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: