Perl:使用循环创建哈希文件

Perl: Create a hash file using a loop

我从 XML 文件中导入数据,并希望将内容输出到日志文件中。为此,我为每个实体创建了一个标量 (2)。为了使用循环输出实体,我创建了一个散列(3 和 4b),并使用 for 循环输出标签(实体)的名称和值 (5)。要获得指定的顺序,我使用 Tie::IxHash。现在,我想知道是否可以使用 for 循环来避免步骤 (3) 和 (4b)。例如,我可以将标量 $x1$x2$x3 放入一个数组中,然后循环执行步骤 (3) 和 (4b)。可能吗?

use strict; 
use warnings;
use Data::Dumper;
use Tie::IxHash;

my $x1 = 'a';
my $x2 = '';
my $x3 = undef;  # no xml tag <x3>; 
 
# (3) Create a hash to output values in a log files using for
my $rx1 = $x1;
my $rx2 = $x2;
my $rx3 = $x3;

# (4a) To make an ordered hash use Tie::IxHash
my %h;
tie %h, 'Tie::IxHash'; 
%h = ( 'x1' => $rx1
     , 'x2' => $rx2
     , 'x3' => $rx3);

# (4c) Output hash with undex content gives a warning 
print map { "$_ ${$h{$_}}\n" } keys %h;   # 51
# Use of uninitialized value in concatenation (.) or string at test.pl line 51. 

print "--------\n";
# (5) Output content of hash into a log file
print "using keys from hash:\n";
foreach my $k (keys %h)  {
    if ( not defined ${$h{$k}} or  ${$h{$k}} eq "" ) {${ $h{$k}} = undef; }
    if ( defined ${$h{$k}} ) { print "$k :  ${$h{$k}} \n";   } else {print  "$k :  undef\n"; }    
}

这给出了输出:

# Output: 
# Use of uninitialized value in concatenation (.) or string at test.pl line 51.
# x1 a
# x2 
# x3 
# --------
# using keys from hash:
# x1 :  a 
# x2 :  undef
# x3 :  undef 

更新 1:

多亏了 Dave Cross,我想到了这个。它对我有用。

#  Define hash [(step (1)-(4)]
%h = ( 'x1' => my $x1
     , 'x2' => my $x2
     , 'x3' => my $x3
     );

# import from xml
$h{x1} = 'a';
$h{x2} = '';
$h{x3} = undef;

# (5) Output content of hash into a log file
print "using keys from hash:\n";
foreach my $k (keys %h)  {
    if ( not defined $h{$k} or  $h{$k} eq "" )  { $h{$k} = undef; }
    if ( defined $h{$k} ) { print "$k :  $h{$k} \n";   } else {print  "$k :  undef\n"; }    
}

更新 2

感谢 choroba 和 Dave Cross 的建议,我进行了简化。现在它简短而有条理。我了解到您可以将接口中的数据直接分配给散列或数组中的标量。通常我喜欢单独声明标量变量,但在这种情况下,如果你有无数的变量,只将它写入散列或数组一次并单独声明散列或数组是有意义的。

#  Define hash [(step (1)-(4)]
%h = ( x1 => $xpc->findvalue('./X1',$node1)
     , x2 => $xpc->findvalue('./X2',$node1)
     , x3 => $xpc->findvalue('./X3',$node1)
     );

# (5) Output content of hash into a log file
print "using keys from hash:\n";
for my $k (keys %h)  {
    if ( not defined $h{$k} or  $h{$k} eq "" )  { $h{$k} = undef; }
    if ( defined $h{$k} ) { print "$k :  $h{$k} \n";   } else {print  "$k :  undef\n"; }    
}

您的 foreach 循环可以更简单一些。

# To enable 'say()' - this is usually at the top of the file
use feature 'say';

for my $k (keys %h)  {
    $h{$k} = undef if defined $h{$k} and $h{$k} eq '';
    say "$k : ", $h{$k} // 'undef';
}
  • 如果您要将其设置为 undef
  • ,请不要检查 undef
  • 使用后缀条件使代码更易于阅读
  • 在打印语句中使用了 // (defined-or) 运算符
  • 使用say()代替print()