【问题标题】:Perl hash not initialising as expectedPerl 哈希未按预期初始化
【发布时间】:2017-07-29 22:58:33
【问题描述】:

我从 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;

%data 完全错误。我必须像 %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,它会跳过该值并使用下一个键作为值。我需要做些什么才能让 %data 正常工作吗?

【问题讨论】:

    标签: perl


    【解决方案1】:

    这个问题是由于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】:

      CGI.pm 已经提供了一种使用Vars 方法的fetch the parameter list as a hash 方法:

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

      多值参数作为压缩字符串返回,由空字符\0 分隔。您必须拆分字符串以获取各个值。

      【讨论】:

        【解决方案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
        

        【讨论】:

          猜你喜欢
          • 2016-10-24
          • 1970-01-01
          • 1970-01-01
          • 2013-09-08
          • 1970-01-01
          • 1970-01-01
          • 2018-04-12
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多