1

我正在使用我找到的 PerlMonk 示例: Reading and Writing Perl Config Files

配置.pl:

%CFG = (
    'servers' => {
        'SRV1' => {
            'IP'     => 99.32.4.0,
            'user'   => 'aname',
            'pswd'   => 'p4ssw0rd',
            'status' => 'unavailable'
        },
        'SRV2' => {
            'IP'     => 129.99.10.5
            'user'   => 'guest',
            'pswd'   => 'guest'
            'status' => 'unavailable'
        }
    },
    'timeout' => 60,
    'log' => {
        'file'  => '/var/log/my_log.log',
        'level' => 'warn',
    },
    'temp' => 'remove me'
);

它工作得很好,但唯一的问题是在读取和写入类似 HASH 的配置时“无序”。有没有办法让它保持绑定?

这很重要,因为配置文件也将被手动编辑,所以我希望键和值的顺序相同。

4

2 回答 2

2

您可以tie在使用它之前配置变量,因此以后的哈希键将保持与以前相同的顺序,

use strict;
use warnings;

use Tie::IxHash;
tie my %CFG, 'Tie::IxHash';

%CFG = (
    'servers' => {
        'SRV1' => {
            'IP'     => '99.32.4.0',
            'user'   => 'aname',
            'pswd'   => 'p4ssw0rd',
            'status' => 'unavailable'
        },
        'SRV2' => {
            'IP'     => '129.99.10.5',
            'user'   => 'guest',
            'pswd'   => 'guest',
            'status' => 'unavailable'
        }
    },
    'timeout' => 60,
    'log' => {
        'file'  => '/var/log/my_log.log',
        'level' => 'warn',
    },
    'temp' => 'remove me'
);

use Data::Dumper;
print Dumper \%CFG;
于 2013-06-06T14:48:55.583 回答
1

如果您使用JSON,那么您的软件可以免受恶意攻击(或者可能是意外损坏)。JSON 的语法也比 Perl 数据结构更简单,并且更容易从语法错误中恢复。

设置该canonical选项将使用按排序顺序的键创建数据,因此每次都为相同的 Perl 数据生成相同的输出。如果您需要按字母顺序以外的特定顺序的数据,那么您可以使用Tie::IxHash@mpaec 在他的回答中描述的模块。

或者,您可以使用该sort_by模块的 Pure Perl 版本中的方法,该方法允许您传递排序规则子例程。这将让您规定键的顺序,并且可以像使用将所有可能的键值与数字排序顺序相关联的哈希一样简单。

该程序使用该sort_by方法以与原始哈希中出现的键相同的顺序重建 JSON。这不太可能是您想要的顺序,但机制就在那里。它通过查找哈希表中的每个键来确定它们应该如何排序。默认情况下,未出现在散列中的任何键(likeSVR1SVR2here)都按字母顺序排序。

use strict;
use warnings;

use JSON::PP ();

my %CFG = (
  'servers' => {
    'SRV1' => {
      'IP'     => '99.32.4.0',
      'user'   => 'aname',
      'pswd'   => 'p4ssw0rd',
      'status' => 'unavailable'
    },
    'SRV2' => {
      'IP'     => '129.99.10.5',
      'user'   => 'guest',
      'pswd'   => 'guest',
      'status' => 'unavailable'
    }
  },
  'timeout' => 60,
  'log'     => {
    'file'  => '/var/log/my_log.log',
    'level' => 'warn',
  },
  'temp' => 'remove me'
);

my %sort_order;
my $n = 0;
$sort_order{$_} = ++$n for qw/ servers timeout log temp /;
$sort_order{$_} = ++$n for qw/ IP user pswd status /;
$sort_order{$_} = ++$n for qw/ file level /;

my $json = JSON::PP->new->pretty->sort_by(\&json_sort);
print $json->encode(\%CFG);

sub json_sort {
  my ($aa, $bb) = map $sort_order{$_}, $JSON::PP::a, $JSON::PP::b;
  $aa and $bb and $aa <=> $bb or $JSON::PP::a cmp $JSON::PP::b;
}

生成此输出

{
   "servers" : {
      "SRV1" : {
         "IP" : "99.32.4.0",
         "user" : "aname",
         "pswd" : "p4ssw0rd",
         "status" : "unavailable"
      },
      "SRV2" : {
         "IP" : "129.99.10.5",
         "user" : "guest",
         "pswd" : "guest",
         "status" : "unavailable"
      }
   },
   "timeout" : 60,
   "log" : {
      "file" : "/var/log/my_log.log",
      "level" : "warn"
   },
   "temp" : "remove me"
}

它可以简单地保存到文件中并类似地恢复。

于 2013-06-06T16:34:29.667 回答