检查字符串是否符合perl中多维hashmap的所有值

时间:2013-11-20 14:00:12

标签: perl hashmap hashtable

我有以下要求

  • 阅读示例数据文件/tmp/user_defined_connection.ini

MANAGEMENT=IDL||CIDL
NORTH=IDL,NORTHERN||VIDL,NORTH||IDL,NORTH
SOUTH=IDL,SOUTHERN||CIDL,SOUTH||IDL,SOUTH
  • 此处的每个键都可以包含多个这样的值','表示AND操作和'||'是OR操作

  • 我需要针对另一个字符串$ instance和每个值进行检查,因此我采用第一个密钥管理并获取其值并检查isntance ....

$instance包含IDLCIDL

在下一次迭代中,将针对第二个键NORTH检查相同的实例,如果为true,则该函数应返回NORTH,所以基本上我需要逐个检查每个值的实例,然后返回键我发现最后......下面是编写到现在的代码

#!/sbin/perl -w
use strict;
use Data::Dumper;

my @providerCloudSequence;
my %idlcodes;
open(my $iniFH, '<', '/tmp/user_defined_connection.ini') 
    or die "Unable to open file:$!\n";

while(<$iniFH>) {
    chomp;
    my @providerCloudClass = split('=',$_);
    push @providerCloudSequence, $providerCloudClass[0];
    if ($@) {
        print "Script Failed to get the Sequence....Exiting the Script\n";
        exit 1;
    }

    #my %idlcodes = map { split /=|\s+/; } <$iniFH>;
    my ($k, @r) = split /=|\Q||/;
    $idlcodes{$k} = [ map [ split /,/ ], @r ];
}
if($@){
        print "Script Failed to create the hash....Exiting the Script\n";
        exit 1;
 }
close $iniFH;
print Dumper \%idlcodes;
        my @interfaceSampleAliases = { "AFGHD_NORTH", 
                                           "NORTHERN_IIDID_IPV123", 
                                           "IDL_SOUTH", 
                                           "IDL_SOUTH_IUID", 
                                           "SOUTHERN_IND_IPV" };
        foreach (@interfaceSampleAliases){
            my $correctKey = getCorrectKey($_, %idlcodes, @providerCloudSequence)
            print $correctKey;
        }

}
# Providercloudsequence helps to maintain the precedence of the input file
# idlcodes is the hasp map where key is the key from file and value is an arracy of arrays ...see below the output of same

sub getCorrectKey($$$){
        my $interfaceAlias = $_[0];
        foreach ($_[2]) {
    # This is where I need the help , I want to get the value from 
    # hash %idlcodes using the key from @providerCloudSequence
    # The value of %idlcodes is kind of multiple Arrays where I want to 
    # grep $interfaceAlias against each with a AND in between elements 
    # and OR in between arrays , if true this is match
        }
}

##数据转储输出:哈希看起来像

'NORTH_IPV' => [
                           [
                             'IDL',
                             'NORTHERN'
                           ],
                           [
                             'VIDL',
                             'NORTH'
                           ],
                           [
                             'IDL',
                             'NORTH'
                           ]
                         ],
          'MANAGEMENT' => [
                            [
                              'IDL'
                            ],
                            [
                              'CIDL'
                            ]
                          ],
          'SOUTH_IPV' => [
                           [
                             'IDL',
                             'SOUTHERN'
                           ],
                           [
                             'CIDL',
                             'SOUTH'
                           ],
                           [
                             'IDL',
                             'SOUTH'
                           ]
                         ]
预期产出
InterfaceAlias         correctKey

 "AFGHD_NORTH"           Doesnt Match anything so return NULL
 "NORTHERN_IIDID_IPV123" Doesnt Match anything so return NULL
 "IDL_SOUTH",            SOUTH_IPV
 "IDL_SOUTH_IUID",       SOUTH_IPV
 "SOUTHERN_IND_IPV"      Doesnt Match anything so return NULL
 "IDL_NORTH_IPV"         NORTH_IPV
 "IDL_ABDGJF"            MANAGEMENT

此示例中的检查应如何工作

检查InterfaceAlias是否包含(IDL OR CIDL),然后检查相同的interfaceAlias是否包含[(IDL AND NORTH)OR(VIDL AND NORTH)或(IDL AND NORTHERN),然后检查相同的interfaceAlias是否包含[(IDL AND SOUTH))或(CIDL和SOUTH)或(IDL和SOUTHERN)]

因此我们必须检查hash%idlcodes中的所有值并返回匹配为TRUE的最后一个键

序列由数组@providerCloudSequence

管理

单词的邻接并不重要例如SOUTH_XXX_CIDL甚至“SOUTH IDL IPV WITH SPACES”应该匹配SOUTH_IPV ....这些只是示例它基本上是一个包含匹配....虽然文件的结构是固定的。 ..(数据可能有所不同)

1 个答案:

答案 0 :(得分:1)

我想我会从ini文件构建一个正则表达式表,然后逐个比较字符串。

我建议的代码如下。 get_correct_key现在将所有下划线转换为连字符并跳出所有垃圾,例如,SOUTH-GWS-F-IDL100555236-Primary-1Gb转换为SOUTH-GWS-F-IDL-Primary-Gb。这使我能够大大简化正则表达式。

关于代码的一些注意事项

  • 优于use warnings,而不是将-w添加到shebang行

  • 标识符中的大写字母通常保留给像包这样的全局字符,任何熟悉Perl的人都会感谢你坚持使用简单变量和子程序的小写和下划线

  • $@仅在一段Perl代码无法编译或调用die时设置。它仅由eval捕获,如果您不使用它,则$@上的测试将始终失败

  • 你应该从不在Perl子例程定义上使用原型。它们与其他语言的原型不同,并且不按照您的想法进行操作

我希望这会有所帮助

use strict;
use warnings;

open my $ini, '<', 'user_defined_connection.ini' or die $!;

my @provider_patterns;

while (<$ini>) {
  next unless /\S/;
  chomp;

  my ($key, $data) = split /=/, $_, 2;
  my $regex = join " |\n", map {
    join ' ', map { "(?=.* \\b $_ \\b )" } split /,/;
  } split /\|\|/, $data;

  push @provider_patterns, [ qr/$regex/xi, $key ];
}

my @aliases = (
  'AFGHD_NORTH',
  'NORTHERN_IIDID_IPV123',
  'IDL_SOUTH',
  'IDL_SOUTH_IUID',
  'SOUTHERN_IND_IPV',
  'IDL_NORTH_IPV',
  'IDL_ABDGJF',
  'IDL SOUTH',
  'MANAGEMENT_IPV_IDL100595208',
  'SOUTH-GWS-F-IDL100555236-Primary-1Gb',
);

for my $alias (@aliases) {
  my $found = get_correct_key($alias, \@provider_patterns);
  printf qq{ %-38s %-s\n}, qq{"$alias"}, defined $found ? $found : "Doesn't match anything so return undef";
}

sub get_correct_key {
  my ($alias, $patterns) = @_;
  $alias =~ tr/_/-/;
  $alias = join '-', $alias =~ /[a-z]+/gi;
  my $found;
  for my $pair (@$patterns) {
    my ($re, $key) = @$pair;
    $found = $key if $alias =~ $re;
  }
  $found;
}

<强>输出

 "AFGHD_NORTH"                          Doesn't match anything so return undef
 "NORTHERN_IIDID_IPV123"                Doesn't match anything so return undef
 "IDL_SOUTH"                            SOUTH_IPV
 "IDL_SOUTH_IUID"                       SOUTH_IPV
 "SOUTHERN_IND_IPV"                     Doesn't match anything so return undef
 "IDL_NORTH_IPV"                        NORTH_IPV
 "IDL_ABDGJF"                           MANAGEMENT
 "IDL SOUTH"                            SOUTH_IPV
 "MANAGEMENT_IPV_IDL100595208"          MANAGEMENT
 "SOUTH-GWS-F-IDL100555236-Primary-1Gb" SOUTH_IPV