不区分大小写的哈希密钥perl

时间:2016-11-29 11:07:55

标签: linux perl

问题

我有一个哈希/数组结构,但是有些哈希键的情况并不相同。

我想知道是否有办法处理这种情况,而无需手动检查每个哈希的密钥。

在下面的示例中,我希望打印所有ID / iD / id / Id字段。

示例代码

use warnings;
use strict;


my $Hash = {
   Server  =>   [
                        {
                                Id=>123
                        },
                        {
                                iD=>456
                        },
                        {
                                ID=>789
                        }
                ]

};

for (@{$Hash->{Server}}){
        print "$_->{ID}\n"
        #This is the problematic part
}

其他

perl版本:v5.10.0

这些数据是从其他地方收到的,必须保持相同的情况,上面的例子是最小的,我不能简单地将它们全部更改为相同的情况。

需要更多信息让我知道。

3 个答案:

答案 0 :(得分:5)

嗯,这取决于你的信息来源。这看起来像你已经解析了一些东西,所以可能有更好的解决方案。

然而,根据我们在这里所做的事情,我是这样做的:

for my $entry (@{$Hash->{Server}}){
   #grep, find first match. Dupes discarded. 
   my ( $key ) = grep { /^id$/i } keys %$entry; 
   print "$key => ",$entry -> {$key},"\n";
}

这可以通过grep使用i正则表达式来解决keys上不区分大小写的问题,并抓住先出现的内容。因此,如果您有/id/i的多个匹配项,那么它将是随机的。 (sort可以帮助解决这个问题)

鉴于你正在与XML合作,我可能会稍微回溯一下,抛弃XML::Simple而是这样做:

#!/usr/bin/perl
use strict;
use warnings;

use XML::Twig;

my $twig = XML::Twig -> new ( twig_handlers => { '_all_' => sub { $_ -> lc_attnames }} );
   $twig -> parse ( \*DATA );

print "XML looks like:\n";
$twig -> set_pretty_print ( 'indented_a'); 
$twig -> print;

print "Output:\n";

foreach my $server ( $twig -> get_xpath('//Server') ) { 
    print $server -> att('id'),"\n";
}

__DATA__
<XML>
   <Server ID="123" />
   <Server Id="456" />
   <Server id="789" />
</XML>

或者你可以:

foreach my $server ( $twig -> get_xpath('//Server') ) {
    $server -> lc_attnames;
    print $server -> att('id'),"\n";
}

代替在树枝处理程序中执行此操作。第一个答案将修复&#39;您的所有XML都具有小写属性,这可能不是您想要的。但是,它可能对其他场景有用,这就是为什么我给出了两个例子。

答案 1 :(得分:1)

没有内置的方法可以做到这一点。您可以做的是使用List::Util's first至少获得更少的检查,然后仍然尝试直到一个适合每个键。

use strict;
use warnings;
use feature 'say';
use List::Util 'first';

my $Hash = {
    Server => [
        {
            Id => 123
        },
        {
            iD => 456
        },
        {
            ID => 789
        }
    ]
};

foreach my $thing ( @{ $Hash->{Server} } ) {

    #                     this returns the first match in the list, like grep   
    #   so we need to use it here to return the actual value
    say $thing->{ first { $thing->{$_} } qw/id ID iD Id/ };
}

如果数据结构中有很多其他键,这比查看所有键都要便宜,因为你最多可以查找所有可能的 id 键加一个,最多两个

如果您想要自动生成可能的键列表,并且可以任意混合使用大写和小写字母,请查看this answer

答案 2 :(得分:-1)

我建议你使用正则表达式来忽略使用i标志的密钥大小。

for my $item ( @ { $Hash->{Server} }) {
    for(keys %{$item}) {
        print $item -> {$_},"\n" if /^ID$/i;
    }
}