Config::Simple,如何更改默认输出 header?

Config::Simple, how to change default output header?

使用包 Config::Simple 测试 ini 格式的配置文件的动态生成生成所需的文件,但始终具有相同的 header 部分,其中包括名称文件开头的 Perl 包。 Config::Simple 有修改默认打印的方法吗?我想用一个新名字替换这个名字。包中的某些功能是否可能?

这是一个玩具代码:

#!/usr/bin/perl

use strict;
use warnings;
use Config::Simple;

my $cfg = new Config::Simple(
        syntax => 'ini'
) or die Config::Simple->error();
$cfg->param("Program.mode", "ALL");
$cfg->param("Program.strategies", "1,2,3,4,5,6,7,8,9,10");
$cfg->param("Data.name_specie", "Homo sapiens");
$cfg->write("test.cfg") or die $cfg->error();

输出:

; Config::Simple 4.58
; Mon Mar 16 12:33:55 2020

[Program]
strategies=1,2,3,4,5,6,7,8,9,10
mode=ALL

[Data]
name_specie=Homo sapiens

只是想替换 ; Config::Simple 4.58 行。

提前感谢您的建议。

"Simple" 模块通常并不简单,因为它们会为您做出很多决定。如果你不喜欢这些决定,你就会陷入困境。这个特定的模块已经十多年没有更新了,并且有几个架构问题。如果你想要 INI 文件,请使用不同的模块,例如 Config:: IniFiles, Config::Tiny, or Config::INI 维护和灵活。

我的第一个想法是子类化并覆盖添加 header 的方法,因为它是 hard-baked 到其中一个方法中。这是繁重的,因为该模块使用了 "private" 子例程和包变量的组合。我倾向于先尝试这个,因为我不打扰原始包:

use strict;
use warnings;
use v5.12;

use Config::Simple;

package Local::Config::Simple {
    use parent qw(Config::Simple);

    # generates a writable string
    sub as_string {
        my $self = shift;

        my $syntax = $self->{_SYNTAX} or die "'_SYNTAX' is not defined";
        my $sub_syntax = $self->{_SUB_SYNTAX} || '';
        my $currtime = localtime;
        my $STRING = undef;
        if ( $syntax eq 'ini' ) {
            while ( my ($block_name, $key_values) = each %{$self->{_DATA}} ) {
                unless ( $sub_syntax eq 'simple-ini' ) {
                    $STRING .= sprintf("[%s]\n", $block_name);
                }
                while ( my ($key, $value) = each %{$key_values} ) {
                    my $values = join (Config::Simple::WRITE_DELIM(), map { Config::Simple::quote_values($_) } @$value);
                    $STRING .= sprintf("%s=%s\n", $key, $values );
                }
                $STRING .= "\n";
            }
        } elsif ( $syntax eq 'http' ) {
            while ( my ($key, $value) = each %{$self->{_DATA}} ) {
                my $values = join (Config::Simple::WRITE_DELIM(), map { Config::Simple::quote_values($_) } @$value);
                $STRING .= sprintf("%s: %s\n", $key, $values);
            }
        } elsif ( $syntax eq 'simple' ) {
            while ( my ($key, $value) = each %{$self->{_DATA}} ) {
                my $values = join (Config::Simple::WRITE_DELIM(), map { Config::Simple::quote_values($_) } @$value);
                $STRING .= sprintf("%s %s\n", $key, $values);
            }
        }
        $STRING .= "\n";
        return $STRING;
    }
}

my $cfg = Local::Config::Simple->new(
        syntax => 'ini'
) or die Config::Simple->error();
$cfg->param("Program.mode", "ALL");
$cfg->param("Program.strategies", "1,2,3,4,5,6,7,8,9,10");
$cfg->param("Data.name_specie", "Homo sapiens");
$cfg->write("file.ini") or die $cfg->error();

有效并给出输出:

[Data]
name_specie=Homo sapiens

[Program]
mode=ALL
strategies=1,2,3,4,5,6,7,8,9,10

然而,它打破了几个面向对象的思想,所以我觉得这种做法很不愉快。通过重新定义原始子例程来修复原始包,我可以少做一些工作。然后包变量和子程序仍然有效。先加载原始模块,然后添加重新定义:

use strict;
use warnings;
use v5.12;

use Config::Simple;
no warnings 'redefine';

package Config::Simple {
    # generates a writable string
    sub as_string {
        my $self = shift;

        my $syntax = $self->{_SYNTAX} or die "'_SYNTAX' is not defined";
        my $sub_syntax = $self->{_SUB_SYNTAX} || '';
        my $currtime = localtime;
        my $STRING = undef;
        if ( $syntax eq 'ini' ) {
            while ( my ($block_name, $key_values) = each %{$self->{_DATA}} ) {
                unless ( $sub_syntax eq 'simple-ini' ) {
                    $STRING .= sprintf("[%s]\n", $block_name);
                }
                while ( my ($key, $value) = each %{$key_values} ) {
                    my $values = join (WRITE_DELIM, map { quote_values($_) } @$value);
                    $STRING .= sprintf("%s=%s\n", $key, $values );
                }
                $STRING .= "\n";
            }
        } elsif ( $syntax eq 'http' ) {
            while ( my ($key, $value) = each %{$self->{_DATA}} ) {
                my $values = join (WRITE_DELIM, map { quote_values($_) } @$value);
                $STRING .= sprintf("%s: %s\n", $key, $values);
            }
        } elsif ( $syntax eq 'simple' ) {
            while ( my ($key, $value) = each %{$self->{_DATA}} ) {
                my $values = join (WRITE_DELIM, map { quote_values($_) } @$value);
                $STRING .= sprintf("%s %s\n", $key, $values);
            }
        }
        $STRING .= "\n";
        return $STRING;
    }
}

my $cfg = Config::Simple->new(
        syntax => 'ini'
) or die Config::Simple->error();
$cfg->param("Program.mode", "ALL");
$cfg->param("Program.strategies", "1,2,3,4,5,6,7,8,9,10");
$cfg->param("Data.name_specie", "Homo sapiens");
$cfg->write("file.ini") or die $cfg->error();

我在 Effective Perl Programming 中写了很多关于此的内容作为处理遗留代码的方法。


作为旁注,您询问模块中是否有一些方法。您可以简单地查看源代码以查看发生了什么以及可用的内容。你会看到 header 是 hard-coded 到 as_string.