我从Perl哈希(关联数组)获得意外结果。
我正在尝试从CGI帖子中填充它,其中可能缺少某些表单值。
use strict;
use Data::Dumper;
use CGI;
my $cgi = new CGI;
my %data = (
'key1' => $cgi->param('fkey1'),
'key2' => $cgi->param('fkey2'),
'key3' => $cgi->param('fkey3'),
'key4' => $cgi->param('fkey4'),
'key5' => $cgi->param('fkey5'),
'key6' => $cgi->param('fkey6'),
'key7' => $cgi->param('fkey7'),
'key8' => $cgi->param('fkey8'),
'key9' => $cgi->param('fkey9'),
'key0' => $cgi->param('fkey0'),
);
print "Content-type: text/html\n\n<pre>";
print Dumper \%data;
my $fkey1 = $cgi->param('fkey1');
my $fkey2 = $cgi->param('fkey2');
my $fkey3 = $cgi->param('fkey3');
my $fkey4 = $cgi->param('fkey4');
my $fkey5 = $cgi->param('fkey5');
my $fkey6 = $cgi->param('fkey6');
my $fkey7 = $cgi->param('fkey7');
my $fkey8 = $cgi->param('fkey8');
my $fkey9 = $cgi->param('fkey9');
my $fkey0 = $cgi->param('fkey0');
my %data2 = (
'key1' => $fkey1,
'key2' => $fkey2,
'key3' => $fkey3,
'key4' => $fkey4,
'key5' => $fkey5,
'key6' => $fkey6,
'key7' => $fkey7,
'key8' => $fkey8,
'key9' => $fkey9,
'key0' => $fkey0,
);
print "Content-type: text/html\n\n<pre>";
print Dumper \%data2;
%数据完全错误。我必须像%data2那样做。输出结果如下:
$VAR1 = {
'key9' => 'key0',
'key5' => 'key6',
'key1' => 'key2',
'key7' => 'key8',
'key3' => 'key4'
};
$VAR1 = {
'key9' => undef,
'key5' => undef,
'key6' => undef,
'key8' => undef,
'key0' => undef,
'key3' => undef,
'key2' => undef,
'key1' => undef,
'key4' => undef,
'key7' => undef
};
因此,如果$ cgi-> param('fkey1')为undef,它会跳过该值并使用下一个键作为值。为了让%数据有效,我还需要做些什么吗?
答案 0 :(得分:8)
此问题是由于param
在列表上下文与标量上下文中的行为方式所致。
在标量上下文中,如果参数不存在,param
将返回undef
。在列表上下文中,它返回一个空列表。所以假设你有一个像这样的哈希初始化:
my %data = ( foo => $cgi->param( 'foo' ),
bar => $cgi->param( 'bar' ),
baz => $cgi->param( 'baz' ) );
并假设参数bar
不存在。由于在列表上下文中调用param
,因此传递给哈希初始化的列表最终看起来像这样:
( 'foo', 'foovalue', 'bar', 'baz', 'bazvalue' )
请注意bar
键之后没有任何内容,因为那里返回了一个空列表。
要解决此问题,您可以强制所有对param
的调用进入标量上下文:
my %data = ( foo => scalar $cgi->param( 'foo' ),
bar => scalar $cgi->param( 'bar' ),
baz => scalar $cgi->param( 'baz' ) );
现在列表将如下所示:
( 'foo', 'foovalue', 'bar', undef, 'baz', 'bazvalue' )
世界上的一切都是对的。
答案 1 :(得分:4)
CGI.pm已经提供了fetch the parameter list as a hash使用Vars
方法的方法:
use CGI;
my $q = CGI->new;
my %params = $q->Vars;
多值参数作为由空字符\0
分隔的打包字符串返回。您必须拆分字符串以获取各个值。
答案 2 :(得分:3)
一种方法是为空值提供默认值,因为这会强制param
在标量上下文中返回。它还具有修复使用未初始化的值警告的双重好处:
my %data = (
'key1' => $cgi->param('fkey1') // '',
'key2' => $cgi->param('fkey2') // '',
'key3' => $cgi->param('fkey3') // '',
'key4' => $cgi->param('fkey4') // '',
'key5' => $cgi->param('fkey5') // '',
'key6' => $cgi->param('fkey6') // '',
'key7' => $cgi->param('fkey7') // '',
'key8' => $cgi->param('fkey8') // '',
'key9' => $cgi->param('fkey9') // '',
'key0' => $cgi->param('fkey0') // '',
);
但是,如果此代码不仅仅是一个示例,它可以简化为:
my %data = map {"key$_" => $cgi->param("fkey$_") // ''} (0..9);
顺便说一句,如果您想测试何时在数组上下文中调用类似param的函数,可以使用以下代码:
sub test {
if (wantarray) {
print "<array>\n"; return ();
} else {
print "<scalar> - $_[0]\n";
return undef;
}
}
my %h = (
key1 => test('array'),
key2 => scalar test('scalar'),
key3 => test('logical defined-or') // '',
key4 => test('logical or') || '',
key5 => test('concat') . '',
);
输出显示上述任何方法都可以强制标量上下文。我虽然只使用scalar
或//
:
<array>
<scalar> - scalar
<scalar> - logical defined-or
<scalar> - logical or
<scalar> - concat