Прочитать хэш-файл perl в perl

#perl

#perl

Вопрос:

У меня есть файл, содержащий данные, подобные приведенным ниже:

output.pl

 {
    "A" => {
        "name" => "chetan",
        "age" => "28",
    },
    "B" => {
        "name" => "vivek",
        "age" => "31",
    },
};
  

По сути, это хэш, хранящийся в другом файле.

Как мне написать программу на perl, чтобы загрузить это как хэш в переменной?

Я пробовал что-то вроде этого:

 use Data::Dumper;
use File::Slurp;

my %hash = read_file("output.pl");
print Dumper(keys(%hash));
  

Но я вижу, что там указано нечетное количество элементов, присвоенных хэшу.

Комментарии:

1. Я не уверен, какие методы лучше всего использовать, поэтому не буду отвечать. Однако простой способ сделать это есть my $hash = do "output.pl" .

2. Кстати, вам, вероятно, следует, print Dumper %hash а не print Dumper(keys(%hash)) .

3. Вы также могли бы взглянуть на Config::Hash .

4. Потому что, если он output.pl содержит что-то вроде system "rm -rf /" , вам не понравится то, что do "output.pl" только что было сделано. Тогда как, если бы вы просто регулярно анализировали свой файл, это не было бы проблемой. Но еще раз, у меня нет какого-либо твердого мнения по этому вопросу, поэтому я просто подожду, пока другие люди поделятся своими мыслями

5. import это не ключевое слово perl, которое вы хотели use . Избегайте File::Slurp, File::Slurper лучше.

Ответ №1:

Вы можете загрузить такие данные с помощью функции do.

 use strict;
use warnings;

my $file = './output.pl';
my $data = do $file;
# unfortunately 'do' error checking is very fragile
# there is no way to differentiate certain errors from the file returning false or undef
unless ($data) {
  die "couldn't parse $file: $@" if $@;
  die "couldn't do $file: $!" unless defined $data;
  die "$file did not return data";
}
  

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

Некоторыми другими параметрами для конфигурационных файлов, которые не позволяют запускать произвольный код, могут быть JSON и Config::Tiny.

Обязательно используйте ./output.pl и не output.pl ; без ведущего ./ do функция будет выполнять поиск @INC (который больше не содержит текущий каталог в версии 5.26 ), а не просто использовать текущий каталог.

Если вы хотите загрузить файл из того же каталога, что и текущий файл, а не из текущего рабочего каталога (как правило, более надежное решение), смотрите Dir::Self или Path::Tiny или аналогичный, с абсолютным путем, чтобы @INC не выполнялся поиск.

 use Dir::Self;
my $file = __DIR__ . '/output.pl';

use Path::Tiny;
my $file = path(__FILE__)->realpath->sibling('output.pl');
  

Ответ №2:

Я вижу как минимум две проблемы в вашем коде:

  1. вы пытаетесь присвоить содержимое файла хэшу (вместо его оценки)
  2. ваш файл содержит ссылку на хэш, а не сам хэш.

Это один из альтернативных способов загрузки и анализа содержимого файла:

 #!/usr/bin/perl
use warnings;
use strict;

use Data::Dumper;

# replacement for loading external file - not relevant for solution
my $content;
{
    local $/;
    $content = <DATA>;
}
#print "${content}n";

my $hash = eval $content;
die "eval error: $@" if $@;
#print "${hash}n";

print Dumper($hash);

exit 0;

__DATA__
{
    "A" => {
        "name" => "chetan",
        "age" => "28",
    },
    "B" => {
        "name" => "vivek",
        "age" => "31",
    },
};
  

Тестовый запуск:

 $ perl dummy.pl
$VAR1 = {
          'A' => {
                   'name' => 'chetan',
                   'age' => '28'
                 },
          'B' => {
                   'name' => 'vivek',
                   'age' => '31'
                 }
        };
  

Ответ №3:

Как и выше с Slurp, в одной строке.

 use File::Slurp ;

# no easy way to get current Mojolicious config, so this is a hack
my $config  = eval (read_file( '/etc/smsmap/sms_map.conf'));