Что означает то, когда Вы пытаетесь распечатать массив или хеш, и Вы видите следующее; Массив (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)
Вы печатаете ссылку на хэш или массив, а не его содержимое.
В конкретном коде, который вы описываете, я припоминаю, что 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 в глубоких черновиках, то даже самый простой код не может быть объяснен.
Трудно сказать, имели вы это в виду или нет, но причина, по которой вы получаете ссылки на массив, заключается в том, что вы печатаете не то, что думаете.
Вы начали правильно, выполнив итерацию по "строкам" @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";
}
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;
. Вот так просто!
Это означает, что у вас нет массива; у вас есть ссылка на массив.
Обратите внимание, что массив указывается в круглых скобках - как список; когда вы используете обозначение квадратных скобок, вы создаете ссылку на массив.
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