Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl hash not initialising as expected

Tags:

perl

I am getting unexpected results from a Perl hash (associative array).

I am trying to populate it from a CGI post, where some form values might be missing.

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 is completely wrong. I have to do it like %data2. The output of this is:

$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
  };

So if $cgi->param('fkey1') is undef, it skips the value and uses the next key as the value. Is there something I need to do to get %data working?

like image 358
Yusuf Moola Avatar asked Dec 03 '25 08:12

Yusuf Moola


2 Answers

This problem is due to the way that param behaves in list context vs. scalar context.

In scalar context, if a parameter doesn't exist, param returns undef. In list context, it returns an empty list. So suppose you have a hash initialization like this:

my %data = ( foo => $cgi->param( 'foo' ),
             bar => $cgi->param( 'bar' ),
             baz => $cgi->param( 'baz' ) );

And suppose that the parameter bar does not exist. Since param is called in list context, the list passed to the hash initialization ends up looking like this:

( 'foo', 'foovalue', 'bar', 'baz', 'bazvalue' )

Note that there's nothing after the bar key, because an empty list was returned there.

To fix it, you can force all calls to param into scalar context:

my %data = ( foo => scalar $cgi->param( 'foo' ),
             bar => scalar $cgi->param( 'bar' ),
             baz => scalar $cgi->param( 'baz' ) );

Now the list will look like this:

( 'foo', 'foovalue', 'bar', undef, 'baz', 'bazvalue' )

And everything is right with the world again.

like image 157
friedo Avatar answered Dec 05 '25 14:12

friedo


CGI.pm already provides a way to fetch the parameter list as a hash using the Vars method:

use CGI;

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

Multi-valued parameters are returned as a packed string separated by the null character \0. You have to split the string to get the individual values.

like image 40
ThisSuitIsBlackNot Avatar answered Dec 05 '25 14:12

ThisSuitIsBlackNot



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!