Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/eclipse/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl 带有Config::ini文件的节继承_Perl_Ini - Fatal编程技术网

Perl 带有Config::ini文件的节继承

Perl 带有Config::ini文件的节继承,perl,ini,Perl,Ini,我有一个PHPINI文件,我需要用Config::IniFiles解析和读取它。在此ini文件中,是从其他部分继承其设置的部分。结构如下所示: [section1] ... ... [section2:section1] ... ... [section3:section2] ... ... 等等 现在,如果我想从section3读取一个键的值,该对象将返回unde,因为它只知道sectionsection3:section2。正如您可能已经预料到的那样,这不是继承所需要的行为。在我的例子中,

我有一个PHPINI文件,我需要用
Config::IniFiles
解析和读取它。在此ini文件中,是从其他部分继承其设置的部分。结构如下所示:

[section1]
...
...
[section2:section1]
...
...
[section3:section2]
...
...
等等


现在,如果我想从
section3
读取一个键的值,该对象将返回unde,因为它只知道section
section3:section2
。正如您可能已经预料到的那样,这不是继承所需要的行为。在我的例子中,我希望对象首先尝试从
section3
读取值,如果在那里找不到,则尝试
section2
,然后尝试
section1
。有没有办法用这个模块实现这一点,或者我必须自己编写一个包装器模块并实现这个功能?

我找不到实现配置继承的Perl模块

但是编写一个简单的过滤器来计算继承并没有那么复杂。给定一个HoH,如果我们将配置中的每个条目视为一个增量,我们可以像下面那样解析继承:

use Algorithm::C3;  # must be installed from CPAN

sub resolve_inheritance {
  my $input = shift;
  my %output;

  # hash of arrays where the arrays contain all parents
  my %child_parent_relations =
    map { my ($c, @p) = split /\s*:\s*/; $c => [\@p, $input->{$_}] } keys %$input;
  my $get_parents = sub { @{ $child_parent_relations{shift()}[0] } };
  my $get_data    = sub {    $child_parent_relations{shift()}[1] };

  # prepare stuff for C3 resolution
  my $resolution_cache = {};
  my $resolve = sub {
    my $child = shift;
    Algorithm::C3::merge($child, $get_parents, $resolution_cache);
  };

  # now we go through all childs, and build temporary hashes from the C3 linearization.
  for my $child (keys %child_parent_relations) {
    my @linearization = $resolve->($child);
    my %temp;
    for my $delta_name (reverse @linearization) {
      my $delta = $get_data->($delta_name);
      @temp{keys %$delta} = values %$delta;
    }
    # save the data in the output:
    $output{$child} = \%temp;
  }

  return \%output;
}
测试:

如您所见,这提供了
-操作符的右关联性(从右到左组合)

如果需要深度优先分辨率,即:

my $expected = {
  's1' => { A => 1 },
  's2' => { A => 2, B => 2 },
  's3' => { A => 1, B => 3, C => 3 },
  's4' => { A => 1, B => 3, C => 3 },  # s3 completely overwrites s2
};
然后你会得到一个不同的结果。这可以通过首先继承每个父级,然后仅合并直接父级,而不是整个层次结构来实现。在单继承的情况下,深度优先线性化和C3分辨率的结果是等效的

为了支持深度优先分辨率,我们交换了上面代码中的
$resolve
函数,并将其更改为

my $resolve; $resolve = sub {
  my $child = shift;
  return $child, map { $resolve->($_) } $get_parents->($child);
};
这是最小的更改,但当然可以通过只保留每个父项最左边的引用来提高效率:

use List::MoreUtils 'uniq';

my $resolve; $resolve = sub {
  my $child = shift;
  return uniq $child, map { $resolve->($_) } $get_parents->($child);
};
如果用于输入的数据结构能够记住节的顺序,那么这种深度优先的解决方案将变得更加容易。然而,散列是无序的

use List::MoreUtils 'uniq';

my $resolve; $resolve = sub {
  my $child = shift;
  return uniq $child, map { $resolve->($_) } $get_parents->($child);
};