Выгрузка файла yaml с использованием perl
Я пытаюсь вывести файл yaml в определенном формате, как указано ниже; Как мне определить мой хэш (% базы данных), если мне нужно вывести что-то вроде ниже?
-name:Fred
Language:python
-name:Barney
Language:perl
-name: Betty
Language:java
-name:Wilma
Language:ruby
open FILE, '>>', "database.txt";
print FILE Dump(\%database);
1 ответ
Структура, которую вы показываете, представляет собой массив хэшей. Таким образом, вам нужно использовать массив, а не хеш. Массив содержит хеш-ссылки.
use YAML 'Dump';
my @database = (
{
name => 'Fred',
Language => 'python',
},
{
name => 'Barney',
Language => 'perl',
},
);
print Dump( \@database );
Это будет выводить
---
- Language: python
name: Fred
- Language: perl
name: Barney
По умолчанию YAML сортирует ключи по алфавиту. Вот почему язык на первом месте. Вы можете отключить это, установив $YAML::SortKeys = 0
,
Однако вы не можете поддерживать порядок элементов в отдельных хешах так, как вы их помещаете в свой код, потому что хеши в Perl никогда не упорядочиваются 1. Заказ случайный. Таким образом, вы не можете гарантировать, что имя будет первым ключом. Это может быть на вашей машине, но не на моей.
Существует способ форсировать порядок, но он будет работать только для очень ограниченного варианта использования. Вы можете установить $YAML::SortKey
на ссылку на массив ключей, и он сохранит этот порядок. Эта функция кажется недокументированной и помечена как хак в коде.
local $YAML::SortKeys = [qw/name Language/];
print Dump( \@database );
Теперь мы получаем
---
- name: Fred
Language: python
- name: Barney
Language: perl
Если ваша структура данных содержит больше вещей, это может сделать не так, как вы хотите.
Вы также можете использовать Bless
функция, экспортируемая YAML, которая присоединяет дополнительную метаинформацию к структуре данных. Он может фильтровать и сортировать определенные узлы. Но вам придется создать некоторую логику, чтобы выбрать, какие узлы вашей структуры данных вы хотите, чтобы это затронуло.
use YAML qw'Bless Dump';
my @database = (
{
name => 'Fred',
Language => 'python',
},
{
name => 'Barney',
Language => 'perl',
},
);
Bless($_)->keys( [qw/name Language/] ) for @database;
print Dump( \@database );
Это также дает тот же результат
---
- name: Fred
Language: python
- name: Barney
Language: perl
Обратите внимание, что это не меняет структуру данных, а скорее дает YAML знать о происходящем. Следовательно, вы не можете использовать на месте map
чтобы сделать это, потому что вы не хотите, чтобы сбросить объекты, созданные им, но фактические данные.
print Dump( [ map { Bless($_)->keys( [qw/name Language/] ) } @database ] );
Это даст вам дамп объектов. Это не то, что вы хотите. Вам нужно будет вернуться $_
после звонка Bless
,
print Dump( [ map { Bless($_)->keys( [qw/name Language/] ); $_ } @database ] );
Но это трудно читать и не дает никаких преимуществ. for
Решение намного понятнее.
1) На самом деле, в старых Perls порядок случайный, но последовательный на той же машине. Это было немного ошибка. Не надейся на это никогда!