填充配置文件

时间:2018-03-01 06:29:14

标签: perl

我正在阅读一个文件standard.p.config,其行有缩进。

该文件包含必须从服务器填写的字段。

检索值后,程序会创建一个输出文件,并为字段填充字段值。

但是当标准文件有缩进时,输出文件不会填充正确的值。

我在输出文件中需要这些缩进以供进一步处理。

standard.p.config文件

DESCRIPTION: Config for lddfvt testcases
AUTO_PROVISIONED:
  HMC_HMC1_NAME:
  HMC_HMC1_PASS:abc123
  MANAGEDMC_MANAGEDMC_NAME:p9zzd-fsp
  LPAR_LPAR1_NAME:
  LPAR_LPAR1_PASSWD:passw0rd
  LPAR_LPAR2_NAME:
  LPAR_LPAR2_PASSWD:passw0rd
 os_env:AIX
 nodecount:2
 default_host:host1
 default_con_mode:telnet
 host1:$LPAR_LPAR1_NAME
 host1_login:root
 host1_password:$LPAR_LPAR1_PASSWD
 host1_test_slot:
 host1_test_slot1:
 host1_test_slot2:
 exact_match_mcast_counter:32
 host2:$LPAR_LPAR2_NAME
 host2_login:root
 host2_password:$LPAR_LPAR2_PASSWD
 host2_pp_slot:
 host2_pp_slot1:
 back_to_back_setup:
 switch1:
 switch1_vendor:BNT
 switch1_login:admin
 switch1_password:admin
 host1_switch1_port1:
 host1_switch1_port2:
 host2_switch1_port1:
 host1_test_ip1:
 host2_test_ip1:
 host1_test_ip2:
 host2_test_ip2:
 ip_netmask:255.255.255.0
 mcast_ip1:225.1.2.6
 mcast_ip2:225.1.2.7
 unicast_test_mac:0x00:11:22:22:33:33
 vlan_tag_id:
 vlan_tag_id2:
 long_run_duration:1
 eid_run_duration:1
 FIRING_NODE:$LPAR_LPAR3_NAME
SCRIPTS: ~

直到LPAR_LPAR2_PASSWD它有两个缩进,然后每行一个缩进。

这个代码

open FILE1, "/home/jenkins/config/standard.p.config" or die;

my %hash;

while ( my $line = <FILE1> ) {
    chomp( $line );

    ( my $word1, my $word2 ) = split /:/, $line;    #/
    my $config_filename = "/home/jenkins/config/$filename";

    # write a switch to match your variable and fill in place of word2;
    # if paattn matches then $word2=$var;

    # $hash{$word1} = $word2;

    switch ( $word1 ) {
        case "LPAR_LPAR1_NAME"     { $word2 = "$host1" }
        case "LPAR_LPAR2_NAME"     { $word2 = "$host2" }
        case "host1_test_slot"     { $word2 = "$host1_test_slot" }
        case "host1_test_slot1"    { $word2 = "$host1_test_slot1" }
        case "host1_test_slot2"    { $word2 = "$host1_test_slot2" }
        case "host2_pp_slot"       { $word2 = "$host2_pp_slot" }
        case "host2_pp_slot1"      { $word2 = "$host2_pp_slot1" }
        case "switch1"             { $word2 = "$Switch_IP" }
        case "host1_switch1_port1" { $word2 = "$host1_switch1_port1" }
        case "host1_switch1_port2" { $word2 = "$host1_switch1_port2" }
        case "host2_switch1_port1" { $word2 = "$host2_switch1_port1" }
        case "host1_test_ip1"      { $word2 = "$host1_test_ip1" }
        case "host1_test_ip2"      { $word2 = "$host1_test_ip2" }
        case "host2_test_ip1"      { $word2 = "$host2_test_ip1" }
        case "host2_test_ip2"      { $word2 = "$host2_test_ip2" }
        case "vlan_tag_id"         { $word2 = "$vlan_tag_id" }
        case "vlan_tag_id2"        { $word2 = "$vlan_tag_id2" }
        case "back_to_back_setup"  { $word2 = "$back_to_back_setup" }
        case "vlan_tag_id2"        { $word2 = "$vlan_tag_id2" }
        case "back_to_back_setup"  { $word2 = "$back_to_back_setup" }
        case "HMC_HMC1_NAME"       { $word2 = "$HMC_HMC1_NAME" }
        case "unicast_test_mac"    { $word2 = "0x00:11:22:22:33:33" }
    }

    $hash{$word1} = $word2;

    open( my $fh, '>', $config_filename ) or die "Could not open file '$config_filename' $!";
    print $fh Dump \%hash;
    close $fh;
}

1 个答案:

答案 0 :(得分:1)

有一些直接错误,首先要解决它们。最后会有一些评论。

case声明

当您在引号(case)下使用"..."值时,会测试它与switch值的相等性,在这种情况下,它会使用{{1}测试字符串相等性}。

但是eq所有$word1都有前导空格,由split /:/保留。这满足了保留它们的要求,但case值中没有一个具有前导空间,因此测试失败。

您想要使用正则表达式匹配

switch ($word1) {
    case /\bLPAR_LPAR1_NAME\b/ { $word2 = $host1 }
    ...
}

表示$word1 =~ m/\bLPAR_LPAR1_NAME\b/,并根据您的文件匹配。

需要字边界锚点\b来区分彼此包含的字符串,例如hosthost1以及host1_test_slot。感谢Borodin发表评论。有关初学者的信息,请参阅perlretut

您似乎正在使用Switch模块。请注意,它是一个具有非常复杂行为的源过滤器。我建议选择其他结构。下面我使用简单的级联if-elsif作为switch功能的最直接匹配。

输出文件

每次循环都会打开和写入

,每次都会覆盖上一次迭代中写入的那个。循环完成后写输出文件。感谢thanos发表评论。

选择用于汇总结果的数据结构

配置文件显然依赖于行的顺序。在输出中,行AUTO_PROVISIONED:必须跟在输入后面跟随它的相同行。但是,使用散列来组装标记值对会拒绝这一点,因为Perl中的散列本质上是无序的。您可以使用模块保持散列的顺序,但使用数组来收集输出行要简单得多。

这方面的另一个问题是你究竟需要做什么。仅提供缺失值?还有其他方法可以进行处理,但由于问题中没有说明目标,我只能提出这一点。我只是用最直接的替代方案替换switch

您将诊断输出“转储”到磁盘而不说明使用了哪个模块,我宁愿不猜测提供Dump功能的是什么(它不是Data::Dumper)。相反,为什么不写一个配置文件?

提供值的变量是未定义的,因此我只使用字符串文字包含少数几种情况。

use warnings;
use strict;
use feature 'say';

my $file = 'standard.p.config';
open my $fh, '<', $file or die "Can't open $file: $!"; 

my $outfile = $file . '.new';  

my @out_lines;

while (my $line = <$fh>) { 
    chomp($line);

    (my $word1, my $word2) = split /:/, $line;    #/ preserves indentation

    $_ = $word1;  # for cleaner regex below

    if    (/\bLPAR_LPAR1_NAME\b/)     { $word2 = 'host1' } # $host1 not given..
    elsif (/\bLPAR_LPAR2_NAME\b/)     { $word2 = 'host' }
    elsif (/\bhost1_test_slot\b/)     { $word2 = 'host1_test_slot' }
    ...    
    elsif (/\bunicast_test_mac\b/)    { $word2 = '0x00:11:22:22:33:33' }

    push @out_lines, "$word1: $word2";
}
close $fh;

open my $fh_out, '>', $outfile or die "Can't open $outfile: $!";

say $fh_out $_  for @out_lines;

close $fh_out;

考虑更多描述性变量名称而不是$wordN(例如,tagvalue)。在定义字符串后,请将字符串('host')替换为变量($host)。

评论

  • 始终在程序顶部use warnings;use strict;

  • 没有理由对变量($word2 = "$host1")进行双引号;无论如何,它都会被评估。它只会产生误导,甚至会导致细微的问题

  • open中的词法文件句柄(my $fh)明显优于globs(FILE1

  • 使用die打印实际错误时,至少为die $!。 请参阅Error variables in perlvar

感谢Borodin发表评论。