迭代哈希哈希和哈希数组的Perl哈希

时间:2012-08-06 19:23:23

标签: arrays perl hash hash-of-hashes

我再次陷入困境,需要一些帮助。像往常一样,它是我的克星 - 哈希。 本质上,我试图写入数据库,z / OS大型机上的所有软件项目。我已成功进入以下哈希:

$VAR1 = {
    'Product' => {
        'Unicenter CA-Deliver Output Management' => {
            'vendorUniqueKeyRef' => 'CA',
            'swUniqueKey'        => 'RMO',
            'description'        => 'Unicenter CA-Deliver Output Management'
        },
        'Unicenter CA-JCLCheck Utility' => {
            'vendorUniqueKeyRef' => 'CA',
            'swUniqueKey'        => 'JCLCHECK',
            'description'        => 'Unicenter CA-JCLCheck Utility'
        },
        'EREP Environmental Recording Edit Print' => {
            'vendorUniqueKeyRef' => 'IBM',
            'swUniqueKey'        => 'EREP',
            'ProductVersion'     => {
                'version'       => '3',
                'swUniqueKey'   => '5658-260',
                'name'          => 'EREP Environmental Recording Edit Print',
                'versionNumber' => '03'
            },
            'description' => 'EREP Environmental Recording Edit Print'
        },
        'SYSQL' => {
            'vendorUniqueKeyRef' => 'SPLWDGRP',
            'swUniqueKey'        => 'SYSQL',
            'ProductVersion'     => {
                'ProductVersionRelease' => {
                    'releaseNumber' => '01',
                    'swUniqueKey'   => 'SYSQL-21',
                    'name'          => 'SYSQL',
                    'release'       => '1'
                },
                'version'       => '2',
                'swUniqueKey'   => 'SYSQL-2',
                'name'          => 'SYSQL',
                'versionNumber' => '02'
            },
            'description' => 'SYSQL'
        },
        '3270-PC File Transfer Program' => {
            'vendorUniqueKeyRef' => 'IBM',
            'swUniqueKey'        => '3270PCFT',
            'description'        => '3270-PC File Transfer Program'
        },
        'Tivoli OMEGAMON XE on z/OS' => {
            'vendorUniqueKeyRef' => 'IBM',
            'swUniqueKey'        => 'OMXEZO',
            'ProductVersion'     => {
                'version'       => '3',
                'swUniqueKey'   => '5698-A59',
                'name'          => 'Tivoli OMEGAMON XE on z/OS',
                'versionNumber' => '03'
            },
            'description' => 'Tivoli OMEGAMON XE on z/OS'
        },
        'Tivoli OMEGAMON XE for Messaging for z/OS' => {
            'vendorUniqueKeyRef' => 'IBM',
            'swUniqueKey'        => 'OMXEMES',
            'description'        => 'Tivoli OMEGAMON XE for Messaging for z/OS'
        },
        'DB2 Utilities Suite for z/OS' => {
            'vendorUniqueKeyRef' => 'IBM',
            'swUniqueKey'        => 'DB2UTSU',
            'ProductVersion'     => {
                'DB2 Utilities Suite for z/OS' => {
                    'swUniqueKey'   => '5655-N97',
                    'version'       => '9',
                    'versionNumber' => '09'
                },
                'DB2 Utilities Suite' => {
                    'swUniqueKey'   => '5697-E98',
                    'version'       => '7',
                    'versionNumber' => '07'
                }
            },
            'description' => 'DB2 Utilities Suite for z/OS'
        },
        'UMB' => {
            'vendorUniqueKeyRef' => 'CSC',
            'swUniqueKey'        => 'CSCUMB',
            'description'        => 'UMB'
        }
    }
};

最初,一切都很好,我有以下几点:

my $sw = $xmldoc->{'Catalog'}->{'Products'};
my %sw = %{ $sw->{'Product'} };

foreach my $product (keys %sw) {
    print "Now processing $product\n";
    my $version;
    my $release;
    my $description        = $sw{$product}{'description'};
    my $vendorUniqueKeyRef = $sw{$product}{'vendorUniqueKeyRef'};
    my $swUniqueKey        = $sw{$product}{'swUniqueKey'};
    if ($sw{$product}{'ProductVersion'}) {
        $version = $sw{$product}{'ProductVersion'}{'version'};
        if ($sw{$product}{'ProductVersion'}{'ProductVersionRelease'}) {
            $release =
                $sw{$product}{'ProductVersion'}{'ProductVersionRelease'}
                {'release'};
        }
        else {
            $release = 0;
        }
    }
    else {
        $version = 0;
        $release = 0;
    }

    my $fullVersion = "$version.$release";

    print "        ***************\n
    The product is: $product\n
    The description is: $description\n
    The vendorUniqueKeyRef is: $vendorUniqueKeyRef\n
    The ProductVersion is: $fullVersion\n
    The swUniqueKey is: $swUniqueKey\n
    ***************\n";
}

但是,在使用strict时,我一直收到有关使用未初始化变量的错误。我意识到某些软件的版本如" .2"而不是" 2.2"然后看到我没有正确处理一些产品被安装两次不同版本的事实,这是我愚蠢地不能满足的。

我试图解决这个问题,但却发现不是所有的版本都有一个版本,我曾尝试过这个版本,但只有当它们已经安装过一次.......

我已经阅读了从HoH和AoH获取数据的负担,但我无法做到这一点。

基本上我试图使用DBD :: ODBC(我已经为我的程序的其余部分工作)将这个哈希中安装的所有软件的列表放到数据库中,无论它是否有版本,多个版本,版本和发行版,多个版本,没有版本,多个版本......嗯,你得到的想法.......

我感谢任何人可以提供任何有关我当前风格和错误检查的建议。

提前致谢。

2 个答案:

答案 0 :(得分:1)

查看您的产品DB2 Utilities Suite for z/OS。在ProductVersion键中还有另外两个产品名称。所有其他人都没有。

'DB2 Utilities Suite for z/OS' => {
  'vendorUniqueKeyRef' => 'IBM',
  'swUniqueKey' => 'DB2UTSU',
  'ProductVersion' => {
    'DB2 Utilities Suite for z/OS' => {
      'swUniqueKey' => '5655-N97',
      'version' => '9',
      'versionNumber' => '09'
    },
    'DB2 Utilities Suite' => {
      'swUniqueKey' => '5697-E98',
      'version' => '7',
      'versionNumber' => '07'
    }
  },
  'description' => 'DB2 Utilities Suite for z/OS'
},

你需要照顾它。你有XML数据的XML模式吗?

答案 1 :(得分:1)

我认为您正在使用XML::Simple?如果是这样,您最好使用XML解析器,它可以为您提供类似XPath的数据访问权限,例如XML::LibXMLXML::Twig

就目前而言,最好保持标量变量指向哈希结构中的每一步。这将避免多个密钥访问元素以及重复使用相同的哈希访问。您不应该像在my %sw = %{ $sw->{'Product'} }中那样复制到另一个哈希,因为复制所有哈希键和值没有意义。我在下面的代码中使用了my $products = $sw->{Product},然后my $product = $products->{$prodname}my $pv = $product->{ProductVersion}

您还可以使用散列片,并且如果您从散列键周围删除引号,代码应该更清晰(仅当键是字母数字时才有效)。我使用切片在一行中提取前三个产品参数。

这是您向我们展示的一段代码的重写。最大的变化是我检查了是否有ProductVersion/version元素。如果是,那么我将versionProductVersionRelease/releaseProductVersion下方合并。否则,我会在所有 ProductVersion/*元素下执行相同的操作。 //已定义 - 或者如果它们不存在则将这些值默认为零。

我希望这更接近你想要的。

my $products = $sw->{Product};

foreach my $prodname (keys %$products) {

    print "\n\nNow processing $prodname\n";

    my $product = $products->{$prodname};

    my ($description, $vendorUniqueKeyRef, $swUniqueKey) =
            @$product{qw/ description vendorUniqueKeyRef swUniqueKey /};

    my @versions;
    if (my $pv = $product->{ProductVersion}) {
        for my $ver (exists $pv->{version} ? $pv : values %$pv) {
          push @versions, sprintf "%d.%d",
              $ver->{version} // 0,
              $ver->{ProductVersionRelease}{release} // 0;
        }
    } 

    print "***************\n";
    print "The product is: $prodname\n";
    print "The description is: $description\n";
    print "The vendorUniqueKeyRef is: $vendorUniqueKeyRef\n";
    print "The ProductVersion is: $_\n" for @versions;
    print "The swUniqueKey is: $swUniqueKey\n";
    print "***************\n";
}

<强>输出

Now processing DB2 Utilities Suite for z/OS
***************
The product is: DB2 Utilities Suite for z/OS
The description is: DB2 Utilities Suite for z/OS
The vendorUniqueKeyRef is: IBM
The ProductVersion is: 9.0
The ProductVersion is: 7.0
The swUniqueKey is: DB2UTSU
***************

Now processing UMB
***************
The product is: UMB
The description is: UMB
The vendorUniqueKeyRef is: CSC
The swUniqueKey is: CSCUMB
***************

Now processing EREP Environmental Recording Edit Print
***************
The product is: EREP Environmental Recording Edit Print
The description is: EREP Environmental Recording Edit Print
The vendorUniqueKeyRef is: IBM
The ProductVersion is: 3.0
The swUniqueKey is: EREP
***************

Now processing Unicenter CA-JCLCheck Utility
***************
The product is: Unicenter CA-JCLCheck Utility
The description is: Unicenter CA-JCLCheck Utility
The vendorUniqueKeyRef is: CA
The swUniqueKey is: JCLCHECK
***************

Now processing Unicenter CA-Deliver Output Management
***************
The product is: Unicenter CA-Deliver Output Management
The description is: Unicenter CA-Deliver Output Management
The vendorUniqueKeyRef is: CA
The swUniqueKey is: RMO
***************

Now processing 3270-PC File Transfer Program
***************
The product is: 3270-PC File Transfer Program
The description is: 3270-PC File Transfer Program
The vendorUniqueKeyRef is: IBM
The swUniqueKey is: 3270PCFT
***************

Now processing SYSQL
***************
The product is: SYSQL
The description is: SYSQL
The vendorUniqueKeyRef is: SPLWDGRP
The ProductVersion is: 2.1
The swUniqueKey is: SYSQL
***************

Now processing Tivoli OMEGAMON XE for Messaging for z/OS
***************
The product is: Tivoli OMEGAMON XE for Messaging for z/OS
The description is: Tivoli OMEGAMON XE for Messaging for z/OS
The vendorUniqueKeyRef is: IBM
The swUniqueKey is: OMXEMES
***************

Now processing Tivoli OMEGAMON XE on z/OS
***************
The product is: Tivoli OMEGAMON XE on z/OS
The description is: Tivoli OMEGAMON XE on z/OS
The vendorUniqueKeyRef is: IBM
The ProductVersion is: 3.0
The swUniqueKey is: OMXEZO
***************