使用perl转储yaml文件

时间:2017-04-25 02:26:34

标签: perl yaml

我正在尝试以特定格式转储yaml文件,如下所述;如果我必须转储下面的内容,我该如何定义我的哈希值(%database)?

-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 个答案:

答案 0 :(得分:6)

您展示的结构是一系列哈希。因此,您需要使用数组,而不是哈希。该数组包含哈希引用。

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's hashes are never ordered 1 ,您无法按照将它们放入代码中的方式维护各个哈希中元素的顺序。订单是随机的。因此,您无法保证 name 将成为第一个密钥。它可能在你的机器上,但它不在我的机器上。

有一种强制订单的方法,但它只适用于非常有限的用例。 Y ou can set $YAML::SortKey to an array reference个键,它将保持该顺序。此功能似乎没有记录,并在代码中标记为黑客。

local $YAML::SortKeys = [qw/name Language/];
print Dump( \@database );

我们现在得到

---
- name: Fred
  Language: python
- name: Barney
  Language: perl

如果您的数据结构包含更多内容,则可能无法满足您的需求。

您还可以使用Bless function exported by 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中,顺序是随机的,但在同一台机器上是一致的。那是一个小错误。不要依赖它!