2014-03-24 112 views
1

我得到了來自Perl哈希(關聯數組)的意外結果。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->參數(「fkey1」)是民主基金,它跳過值,並使用下一個鍵的值。有什麼我需要做的,以獲得%的數據工作?

回答

7

此問題是由於的方式,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') 

一切是正確的與世界一次。

2

一種方法是爲空值提供默認值,因爲這會強制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 
3

CGI。時已經提供了使用Vars方法的方式來fetch the parameter list as a hash

use CGI; 

my $q = CGI->new; 
my %params = $q->Vars; 

多值參數返回由空字符\0分離的填充字符串。您必須拆分字符串以獲取單個值。