Config :: IniFiles哈希行为与手动编写的哈希

时间:2017-07-21 14:01:16

标签: perl hash reference config

我正在加载一个配置文件,该文件以Config::IniFiles结尾为嵌入式哈希。之后,我想修改结果哈希,对于某些键,将其值提高一级。在下面的例子中,我的目标是:

$VAR1 = {
          'max_childrensubtree' => '7',
          'port' => '1984',
          'user' => 'someuser',
          'password' => 'somepw',
          'max_width' => '20',
          'host' => 'localhost',
          'attrs' => {
                       'subattr2' => 'cat',
                       'topattr1' => 'cat',
                       'subattr2_1' => 'pt',
                       'subattr1' => 'rel'
                     },
          'max_descendants' => '1000'
        };

因此,对于最高级别的密钥paramsbasex,我想将其内容(键值对)移动到最高级别 - 并自行删除项目。简而言之:

(
  a => {
    'key1' => 'ok',
    'key2' => 'hello'
  }
)

变成

(
  'key1' => 'ok',
  'key2' => 'hello'
)

奇怪的是,我正在尝试做的是处理从读取INI文件构建的哈希,但它确实可以使用手动插入的哈希。换句话说,这有效:

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

use Data::Dumper;

my %ini = (
        'params' => {
                      'max_width' => '20',
                      'max_childrensubtree' => '7',
                      'max_descendants' => '1000'
                    },
        'attrs' => {
                     'topattr1' => 'cat',
                     'subattr1' => 'rel',
                     'subattr2' => 'cat',
                     'subattr2_1' => 'pt',
                   },
        'basex' => {
                     'host' => 'localhost',
                     'port' => '1984',
                     'user' => 'someuser',
                     'password' => 'somepw'
                   }
);

&_parse_ini(\%ini);

sub _parse_ini {
  my $ref = shift;

  foreach (('params', 'basex')) {
    foreach my $k (keys %{$ref->{$_}}) {
        $ref->{$k} = $ref->{$_}->{$k};
    }
    delete $ref->{$_};
  }

  print Dumper($ref);
}

但这不是:

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

use Data::Dumper;
use Config::IniFiles;

# Load config file
tie my %ini, 'Config::IniFiles', (-file => $ARGV[0]);

&_parse_ini(\%ini);

sub _parse_ini {
  my $ref = shift;

  foreach (('params', 'basex')) {
    foreach my $k (keys %{$ref->{$_}}) {
        $ref->{$k} = $ref->{$_}->{$k};
    }
    delete $ref->{$_};
  }

  print Dumper($ref);
}

此示例的输入ini文件为:

[params]
max_width = 20
max_childrensubtree = 7
max_descendants = 1000

[attrs]
topattr1 = cat
subattr1 = rel
subattr2 = cat
subattr2_1 = pt

[basex]
host = localhost
port = 1984
user = admin
password = admin

我一直在查看文档和SO上的类似问题,但没有找到。似乎哈希是相同的(Config :: IniFiles似乎没有添加特定的东西),所以我不知道为什么它适用于'手动'哈希,而不适用于读入哈希。

1 个答案:

答案 0 :(得分:2)

这两个哈希值完全不相同,尽管它们似乎是从它们包含的数据的角度来看。

第一个是常规哈希。你可以用它做任何你喜欢的事。

第二个是捆绑哈希。它成为Config :: IniFiles的一个对象,但是具有类似哈希的接口。因此,虽然它看起来像是一个哈希,但是包可以覆盖在哈希中存储或获取信息的方法。

在这种特殊情况下,如果值为hash ref,Config :: IniFiles只会在哈希中存储新的键值。因此,您无法根据需要将捆绑的哈希展平。相反,您必须创建一个新哈希并将数据复制到其中以执行您想要的操作。