Выгрузка файла 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 порядок случайный, но последовательный на той же машине. Это было немного ошибка. Не надейся на это никогда!

Другие вопросы по тегам