【问题标题】:IniFiles use array or hashIniFiles 使用数组或散列
【发布时间】:2017-07-02 15:53:06
【问题描述】:

我必须将 PHP 脚本转换为 Perl。

在我的 PHP 脚本中,我解析了一个包含数组元素的 ini 文件,例如...

[RADIUS]
SRV[] = "server 1"
SRV[] = "server 2"
SRV[] = "server 3"
...
SRV[] = "server n"

这在 PHP 中运行良好,我的问题是,我可以在 Perl 中使用相同的 ini 文件还是必须将其重写如下

[RADIUS]
SRV1 = "server 1"
SRV2 = "server 2"
SRV3 = "server 3"
...
SRV4 = "server n"

这在 CPAN 中并不清楚。

对于第一个变体,我可以遍历哈希并使用 while 循环读取我的值,或者如果我删除编号一致的项目,我不必小心。

欢迎任何提示!提前谢谢你。

【问题讨论】:

  • 您使用 CPAN 中的哪个模块来执行此操作?
  • edit 并显示您编写的代码以及您想对配置执行的操作。如果这些服务器的东西最终排列在一个阵列中,这很重要吗?你需要它们井井有条吗?

标签: perl file hash ini


【解决方案1】:

您可以直接使用您的 ini 文件,但有些曲折。

根据docs

val ($section, $parameter [, $default] )

返回节中指定参数($parameter)的值 $section,如果没有节或没有节,则返回 undef(或 $default,如果指定) 给定部分的参数存在。

如果您希望将多行/值字段作为数组返回,只需 指定一个数组作为接收者:

@values = $cfg->val('Section', 'Parameter');

多行/值 在标量上下文中返回的字段将使用 $/ 连接 (输入记录分隔符,默认为 \n)如果定义,否则 值将使用 \n 连接。

以下内容:

use 5.014;
use warnings;
use Config::IniFiles;

use Data::Dumper;

my $cfg = Config::IniFiles->new( -file => "./conf.ini" );
my @v = $cfg->val( 'RADIUS', 'SRV[]' );
say Dumper \@v;

产生一个 4 元素数组,

$VAR1 = [
          '"server 1"',
          '"server 2"',
          '"server 3"',
          '"server n"'
        ];

另请注意:

  • 使用SRV[] 作为参数名称。
  • 并且返回的数组元素包含" 引号字符。

【讨论】:

  • 投反对票的人能否评论我如何改进答案?
【解决方案2】:

如果您熟悉一点正则表达式,也可以逐行读取文件并存储所需的值。我在下面的示例中使用了它。

如果您不需要“服务器 1”、“服务器 2”.. 值的特定顺序,那么您可以使用 Hash,否则,请使用数组。

这里,从你的例子,一个示例测试文件:

%_Host@User> cat srv.txt
SRV[] = "server 1"
SRV[] = "server 2"
SRV[] = "server 3"
SRV[] = "server 109"
SRV[] = "server 51"
%_Host@User>

我通过将文件添加到脚本来读取它,然后生成一个哈希和一个数组,如下面的 Data::Dumper 输出所示。

%_Host@User> cat srv.txt |perl test.pl

# Hash output [unordered]
$VAR1 = '"server 109"';
$VAR2 = 1;
$VAR3 = '"server 51"';
$VAR4 = 1;
$VAR5 = '"server 1"';
$VAR6 = 1;
$VAR7 = '"server 3"';
$VAR8 = 1;
$VAR9 = '"server 2"';
$VAR10 = 1;

# Array output [in order]
$VAR1 = '"server 1"';
$VAR2 = '"server 2"';
$VAR3 = '"server 3"';
$VAR4 = '"server 109"';
$VAR5 = '"server 51"';
%_Host@User>

现在您有两种选择,您可以按照自己的意愿进行操作。

这是脚本:它的逻辑是:如果行匹配'server'然后处理并提取值并存储在哈希和数组中,否则跳过。

#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper ;
my %hash ;
my @array ;

while (<>)
{
  if (m/server/) {
    if (m/^.+? = (.+)$/) {
      $hash{$1} = 1 ;
      push (@array, $1) ;
    }
  }
}

print Dumper %hash ;
print Dumper @array ;

【讨论】:

  • 既然已经有好几个模块来做这件事,为什么还要重新发明轮子?
  • @simbabque:为了原创。 :)
  • 不要重新发明轮子。 CPAN 模块通常具有用于自动化测试的测试套件,并且大多数可以处理特殊情况。您可以为自己重新发明轮子,但是当有 CPAN 模块时,请不要在这里将其用作答案。
【解决方案3】:

这是我使用 Config:IniFiles 为我所做的工作:

use Config::IniFiles;
# Read Ini File
my %MyCfg;
tie %MyCfg, 'Config::IniFiles', ( -file => "..".$MyPathSep."ini".$MyPathSep."file.ini" );
foreach my $List1 (sort keys %{$MyCfg{'DataCenters'}}) {
    if (ref $MyCfg{'DataCenters'}{$List1} eq 'ARRAY') {
        foreach my $List2 (sort keys @{$MyCfg{'DataCenters'}{$List1}}) {
            print $MyCfg{'DataCenters'}{$List1}[$List2]."\n";
        }
    } else {
        print $MyCfg{'DataCenters'}{$List1}."\n";
    }
}

对于输入部分:

[DataCenters]
; DC in location a
LOCa[] = "DC1"
LOCa[] = "DC2"
LOCa[] = "DC3"
LOCa[] = "DC4"
; DC in location b
LOCb[] = "DC5"

输出是:

 scripts\bin>perl switchcfg.pl
    "DC1"
    "DC2"
    "DC3"
    "DC4"
    "DC5"

感谢您的贡献! 问候 洛朗

【讨论】:

    猜你喜欢
    • 2015-10-09
    • 2014-05-19
    • 2010-12-04
    • 1970-01-01
    • 2022-11-20
    • 1970-01-01
    • 2016-03-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多