Могу ли я превратить строку, которая выглядит как содержимое массива в массив? - PullRequest
3 голосов
/ 25 января 2012

У меня есть строка, считанная из текстового файла, которая будет эквивалентна моей декларации в следующем формате:

$string = '["Item1_Field1","Item1_Field2","Item1_Field3"],["Item2_Field1","Item2_Field2","Item2_Field3"],["Item3_Field1","Item3_Field2","Item3_Field3"],["Item4_Field1","Item4_Field2","Item4_Field3"]';

(Фактическая строка содержит около 600 элементов и около 50 полей). ЧтоЯ пытаюсь сделать, это получить двумерный (вложенный) массив элементов и полей, так что я могу ссылаться на них, используя что-то вроде:

print $ItemsAndFields[1][2]

, что приведет к (с учетом нуля-основанные массивы):

Item2_Field3

Мне приходит в голову, что строка имеет формат, очень похожий на то, как вы объявляете массив в Perl, поэтому я надеюсь, что есть что-то похожее на следующееПозвольте мне назначить элементы массиву напрямую:

@ItemsAndFields = magicfunction( $string );

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

Единственный способ, которым я могучтобы сделать это иначе, нужно использовать функцию split дважды для создания этого массива массива.Следующее непроверено, просто работа в моей голове:

$string =~ s/\[//g;
my @items = split(/\],*/, $string);
my @ItemsAndFields = split(/\,/, $string);

Я пытался посмотреть на функцию eval (), использование {} ссылок, а также поиск по этому сайту, но это труднознаю, что мне нужно искать.

Любая помощь приветствуется, я новичок в Perl.

Ответы [ 3 ]

5 голосов
/ 25 января 2012
my $arrayRef = eval "[$string]";

даст вам:

$arrayRef = [
      [
        'Item1_Field1',
        'Item1_Field2',
        'Item1_Field3'
      ],
      [
        'Item2_Field1',
        'Item2_Field2',
        'Item2_Field3'
      ],
      [
        'Item3_Field1',
        'Item3_Field2',
        'Item3_Field3'
      ],
      [
        'Item4_Field1',
        'Item4_Field2',
        'Item4_Field3'
      ]
    ];

, к которому вы можете получить доступ следующим образом:

my $item2Field3 = $arrayRef->[1]->[2];
4 голосов
/ 25 января 2012

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

use JSON 'decode_json';

my $data = decode_json "[$string]";

say $$_[0] for @$data;

, который печатает:

Item1_Field1
Item2_Field1
Item3_Field1
Item4_Field1

Это позволяет избежать проблем с оценкой кода в структуре данных.Это также должно быть быстрее, чем eval.

1 голос
/ 25 января 2012

Вы действительно ищете функцию eval. Одна из причин, по которой eval поначалу трудно понять, заключается в том, что есть две разные формы eval, которые очень разные.

  • eval {block}
  • eval "string"

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

Ваш ответ поэтому:

my @ItemsAndFields = eval "($string)";

другие варианты использования eval могут быть

my $name = "Joel";
my $sub = eval 'sub { print "Hello ' . $name . '"}';
$sub->();

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

...