使用xml模块时,“不推荐使用伪哈希”进行故障排除

时间:2011-10-01 04:57:47

标签: perl hash

我正在学习如何使用perl哈希并在perl中遇到此消息。我使用XML::Simple来解析xml输出并使用exists来检查哈希键。

消息: Pseudo-hashes are deprecated at ./h2.pl line 53. Argument "\x{2f}\x{70}..." isn't numeric in exists at ./h2.pl line 53. Bad index while coercing array into hash at ./h2.pl line 53.

我之前使用一个测试目录编写了工作脚本,然后在我收到此消息时在另一个目录上执行脚本以进行测试。我该如何解决/解决这个问题?

错误引用的代码:

use strict;
use warnings;
use XML::Simple;
use Data::Dumper;

#my $data = XMLin($xml);
my $data = XMLin($xml, ForceArray => [qw (file) ]);
my $size=0;

if (exists $data->{class}
       and $data->{class}=~ /FileNotFound/) {
        print "The directory: $Path does not exist\n";
        exit;
          } elsif (exists $data->{file}->{path}
                      and $data->{file}->{path} =~/test-out-00/) {
                    $size=$data->{file}->{size};
                       if ($size < 1024000) {
                          print "FILE SIZE:$size BYTES\n";
                          exit;
                       }
          } else {
            exit;
}

print Dumper( $data );

工作测试用例,数据结构如下所示:

$VAR1 = {
              'recursive' => 'no',
              'version' => '0.20.202.1.1101050227',
              'time' => '2011-09-30T02:49:39+0000',
              'filter' => '.*',
              'file' => {
                        'owner' => 'test_act',
                        'replication' => '3',
                        'blocksize' => '134217728',
                        'permission' => '-rw-------',
                        'path' => '/source/feeds/customer/test/test-out-00',
                        'modified' => '2011-09-30T02:48:41+0000',
                        'size' => '135860644',
                        'group' => '',
                        'accesstime' => '2011-09-30T02:48:41+0000'
                     'modified' => '2011-09-30T02:48:41+0000'
                   },
      'exclude' => ''
    };
recursive:no
version:0.20.202.1.1101050227
time:2011-10-01T07:06:16+0000
filter:.*
file:HASH(0x84c83ec)
path:/source/feeds/customer/test
directory:HASH(0x84c75d8)
exclude:

有看错的数据结构:

$VAR1 = {
          'recursive' => 'no',
          'version' => '0.20.202.1.1101050227',
          'time' => '2011-10-03T04:49:36+0000',
          'filter' => '.*',
          'file' => [
                    {
                      'owner' => 'test_act',
                      'replication' => '3',
                      'blocksize' => '134217728',
                      'permission' => '-rw-------',
                      'path' => '/source/feeds/customer/test/20110531/test-out-00',
                      'modified' => '2011-10-03T04:47:46+0000',
                      'size' => '121406618',
                      'group' => 'feeds',
                      'accesstime' => '2011-10-03T04:47:46+0000'
                    },

测试xml文件:

<?xml version="1.0" encoding="UTF-8"?><listing time="2011-10-03T04:49:36+0000" recursive="no" path="/source/feeds/customer/test/20110531" exclude="" filter=".*" version="0.20.202.1.1101050227"><directory path="/source/feeds/customer/test/20110531" modified="2011-10-03T04:48:19+0000" accesstime="1970-01-01T00:00:00+0000" permission="drwx------" owner="test_act" group="feeds"/><file path="/source/feeds/customer/test/20110531/test-out-00" modified="2011-10-03T04:47:46+0000" accesstime="2011-10-03T04:47:46+0000" size="121406618" replication="3" blocksize="134217728" permission="-rw-------" owner="test_act" group="feeds"/><file path="/source/feeds/customer/test/20110531/test-out-01" modified="2011-10-03T04:48:04+0000" accesstime="2011-10-03T04:48:04+0000" size="127528522" replication="3" blocksize="134217728" permission="-rw-------" owner="test_act" group="feeds"/><file path="/source/feeds/customer/test/20110531/test-out-02" modified="2011-10-03T04:48:19+0000" accesstime="2011-10-03T04:48:19+0000" size="125452919" replication="3" blocksize="134217728" permission="-rw-------" owner="test_act" group="feeds"/></listing>

3 个答案:

答案 0 :(得分:5)

“不推荐使用伪哈希”错误意味着您尝试将数组作为哈希访问,这意味着$data->{file}$data->{file}{path}是一个数组引用。

您可以使用print ref $data->{file}检查数据类型。 Data::Dumper模块还可以帮助您查看数据结构中的内容(可能在设置$Data::Dumper::Maxdepth = N时,如果结构很大,则将转储限制为N个级别。)

<强>更新

现在你正在使用ForceArray,$data->{file}应始终指向一个arrayref,它可能有多个path的引用。这是一段经过修改的代码段来处理它。但请注意,if-then-exit条件的逻辑可能必须改变。

if (defined $data->{class} and $data->{class}=~ /FileNotFound/) {
    print "The directory: $Path does not exist\n";
    exit;
}

exit if ! defined $data->{file};

# filter the list for the first file entry named test-out-00
my ( $file ) = grep { 
    defined $_->{path} && $_->{path} =~ /test-out-00/ 
} @{ $data->{file} };

exit if ! defined $file;

$size = $file->{size};
if ($size < 1024000) {
    print "FILE SIZE:$size BYTES\n";
    exit;
}

答案 1 :(得分:2)

使用XML::Simple时,ForceArray选项是最重要的选项之一,尤其是在输入数据具有可能出现1次或更多次的嵌套元素的情况下。例如:

use XML::Simple;
use Data::Dumper;

my @xml_snippets = (
    '<opt> <name x="3" y="4">B</name> <name x="5" y="6">C</name> </opt>',
    '<opt> <name x="1" y="2">A</name>                            </opt>',
);

for my $xs (@xml_snippets){
    my $data = XMLin($xs, ForceArray => 0);
    print Dumper($data);
}

输出:

$VAR1 = {
  'name' => [      # Array ref because there are 2 <name> elements.
    {
      'y' => '4',
      'content' => 'B',
      'x' => '3'
    },
    {
      'y' => '6',
      'content' => 'C',
      'x' => '5'
    }
  ]
};
$VAR1 = {
  'name' => {      # No intermediate array ref.
    'y' => '2',
    'content' => 'A',
    'x' => '1'
  }
};

通过激活ForceArray选项,您可以指示XML::Simple生成始终使用中间数组引用的一致数据结构,即使只有一个特定嵌套元素也是如此。您可以全局或特定标签激活该选项,如下所示:

my $data = XMLin($xs, ForceArray => 1                );  # Globally.
my $data = XMLin($xs, ForceArray => [qw(name foo bar)]);

答案 2 :(得分:0)

首先,我建议您使用前面讨论过的ForceArray => [qw( file )]。这将导致为file返回一个数组,无论是否有一个或多个file元素。这比使用两种可能的格式更容易处理。

正如我之前所指出的,问题是你没有规定循环多个file元素。你说如果文件不存在你想退出,这意味着你想要

my $found;
for my $file (@{ $data->{file} }) {
   if ($file->{path} =~ m{/test-out-00\z}) {
      $found = $file;
      last;
   }
}

die("Test file not found\n") if !$found;

... do something with file data in $found ...