【问题标题】:Read config hash-like data into perl hash将 config hash-like 数据读入 perl hash
【发布时间】:2014-06-25 05:56:49
【问题描述】:

我有一个配置文件config.txt 喜欢

{sim}{time}{end}=63.1152e6;
{sim}{output}{times}=[2.592e6,31.5576e6,63.1152e6];
{sim}{fluid}{comps}=[ ['H2O','H_2O'], ['CO2','CO_2'],['NACL','NaCl'] ];

我想将其读入 perl 哈希,

my %h=read_config('config.txt');

我已签出模块 Config::Hash ,但它不提供相同的输入文件格式。

【问题讨论】:

  • 首先想到的是等分,然后解析每一边。
  • 先识别文件格式,再找解析器。如果你想发明一个解析器,你要么必须推断“看起来像 Perl,也许它完全像 Perl”,或者更准确地指定格式是什么样的。
  • @TLP 感谢您的评论!它和 Perl 完全一样。
  • 您自己决定了这种文件格式吗?可以使设计更容易编程
  • @HåkonHægland 如果您自己选择数据格式,我建议您使用 JSONYAML 而不是滚动您自己的解决方案。

标签: perl hash


【解决方案1】:

可以自己滚动。使用Data::Diver 遍历哈希,但也可以手动完成。

use strict;
use warnings;

use Data::Diver qw(DiveVal);

my %hash;

while (<DATA>) {
    chomp;
    my ($key, $val) = split /\s*=\s*/, $_, 2;

    my @keys = $key =~ m/[^{}]+/g;

    my $value = eval $val;
    die "Error in line $., '$val': $@" if $@;

    DiveVal(\%hash, @keys) = $value;
}

use Data::Dump;
dd \%hash;

__DATA__
{sim}{time}{end}=63.1152e6;
{sim}{output}{times}=[2.592e6,31.5576e6,63.1152e6];
{sim}{fluid}{comps}=[ ['H2O','H_2O'], ['CO2','CO_2'],['NACL','NaCl'] ];

输出:

{
  sim => {
           fluid  => { comps => [["H2O", "H_2O"], ["CO2", "CO_2"], ["NACL", "NaCl"]] },
           output => { times => [2592000, 31557600, 63115200] },
           time   => { end => 63115200 },
         },
}

如果您能想出一种不使用eval 的方法会更好,但不知道您的数据,我无法准确地提出替代方案。

更好的选择,使用 JSON 或 YAML

如果您自己选择数据格式,我建议您使用JSONYAML 来保存和加载您的配置数据。

use strict;
use warnings;

use JSON;

my %config = (
  sim => {
           fluid  => { comps => [["H2O", "H_2O"], ["CO2", "CO_2"], ["NACL", "NaCl"]] },
           output => { times => [2592000, 31557600, 63115200] },
           time   => { end => 63115200 },
         },
);

my $string = encode_json \%config;

## Save the string to a file, and then load below:

my $loaded_config = decode_json $string;

use Data::Dump;
dd $loaded_config;

【讨论】:

  • 太棒了!这可以与跨越多行的定义一起使用吗?和交错的空行(使配置文件更具可读性)?
  • 这可以调整为允许定义跨越多行并允许空行。但是这段代码本身并不支持这些特性。这主要是作为概念证明,但在不了解您的完整数据的情况下,我无法预测您需要支持的所有功能或边缘情况。
  • 好的,再次感谢.. 顺便说一下,当尝试从文件中读取配置时,我收到错误:Error in line 1, '63.1152e6;': Can't use string ("end") as a SCALAR ref while "strict refs" in use at /home/fcihh/perl5/lib/perl5/Data/Diver.pm line 129
  • 我已经重新排序了这些行,以便 eval 的错误检查将按预期工作..
  • 谢谢米勒.. JSON 也可以正常工作.. 但我看到这里有很多问题需要考虑,例如我想在输入文件中有 cmets.. 我需要更多地考虑这个。但是感谢您的出色回答!
猜你喜欢
  • 1970-01-01
  • 2012-04-19
  • 2020-11-28
  • 2012-01-19
  • 2013-12-03
  • 1970-01-01
  • 2016-03-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多