绑读和写Perl配置文件

时间:2013-06-06 14:04:25

标签: perl file configuration tie

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

Configuration.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时,配置是“乱序”。 有没有办法让它保持联系?

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

2 个答案:

答案 0 :(得分: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;

答案 1 :(得分:1)

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

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

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

此程序使用sort_by方法重建JSON,其顺序与原始哈希中的键出现的顺序相同。这不太可能是你想要的顺序,但机制就在那里。它的工作原理是查找哈希表中的每个键以确定它们的排序方式。默认情况下,哈希中没有出现的任何键(如SVR1SVR2)按字母顺序排序。

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"
}

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