Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I've been trying to get this to work for the past hour, and I'm having no luck.. I know its something stupid that I keep forgetting... What I want to be able to do is to... script.cgi?name=blah&name2=blah2.. to use $data{'name'} to get blah.. and i also am going to be using this script with forms.. so i will have stuff comming in on <STDIN> as well...

Can anyone point out what I need to change in this script in order for this to work?

#!/usr/bin/perl use CGI ':cgi-lib'; my %data = $ENV{'QUERY_STRING'};

Replies are listed 'Best First'.
Re: use CGI
by Masem (Monsignor) on May 24, 2001 at 22:36 UTC
    You're probably looking for Vars:
    use CGI ':cgi-lib'; my $cgi = new CGI; my $hash_ref = $cgi->Vars; print $hash_ref->{'name'};
    Will work with GETs, POSTs, and from command line.
    Dr. Michael K. Neylon - mneylon-pm@masemware.com || "You've left the lens cap of your mind on again, Pinky" - The Brain
Re: use CGI
by arturo (Vicar) on May 24, 2001 at 22:41 UTC

    Or:

    use CGI qw(:standard); my %data = map { $_ => param ($_) } param();

    The second line gets you the same result as

    my %data; foreach my $param ( param() ) { $data{$param}= param($param); }

    A call to param() (a function in the CGI module) in a list context gets you the name of all the parameters passed to the script via POST and GET. param("name") gets you the value of the passed "name" parameter.

    HTH.

    perl -e 'print "How sweet does a rose smell? "; chomp ($n = <STDIN>); +$rose = "smells sweet to degree $n"; *other_name = *rose; print "$oth +er_name\n"'

      arturo wrote:

      my %data = map { $_ => param ($_) } param();

      While that will work for many cases, it fails with a query strings that have multiple values for a single name:

      color=blue&color=red

      There are two ways of resolving this. The first is map all hash keys to list references:

      my %data = map { $_ => [ param($_) ] } param();

      Because param() uses wantarray, it will return a list if called in that context. Accessing param names with a single value become $data{'someval'}->[0]. Some people might think that's a bit weird, so one could also do the following:

      my %data = map { $_ => scalar @{[ param( $_ ) ]} == 1 ? param( $_ ) : +[ param( $_ ) ] } param;

      With the following query string...

      name=fred&color=red&color=blue

      ... the value for name can be accessed with $data{'name'} and the first value for color can be accessed with $data{'color'}->[0]

      I don't like the second method because there winds up being two methods for accessing similar data. This will likely cause problems in the long run. Further, with the multiple calls to param(), it's less efficient. However, I really don't like either method (though I've posted similar stuff before) because when I see people blindly pulling in all of that data, they tend not to untaint it.

      Cheers,
      Ovid

      Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

      what exactly does:

      use CGI qw(:standard); my %data = map { $_ => param ($_) } param();


      that do? whatever it does it worked fine, thanks alot... I'd just like to understand what's going on
      heh
Re: use CGI
by swiftone (Curate) on May 24, 2001 at 23:01 UTC
    As others have alluded, you might want to look into the param() function, but the exact answer to your question is:
    #!/usr/bin/perl -w use strict; #Trust us use CGI; my $query = CGI::new; my %data = $query->Vars();
    This will work if the input came in from STDIN or via a webserver.

    (Note: Masem above uses the same function in a scalar context to get a reference ($data). Used in a list context, Vars() will return a hash, which is what you asked for. Masem's solution is better if you intend to pass the data to subroutines, they work equally well if you treat them as global variables.)

      can i use

      use CGI qw(:standard); my %data = map { $_ => param ($_) } param();
      with both $ENV{'QUERY_STRING'} as well as <STDIN> because when I mannually open a script w/ just query string.. it works fine, but when I have input comming from both query string and <STDIN> it gives me an internal server error.
        I'm not sure I'm clear on how you are using the script. There are three ways to pass data to a CGI script:
        1. On the URL: script.cgi?foo=bar
        2. Via a web POST (i.e. sent w/the HTTP request).
        3. via STDIN, which is normally only used as a CGI debugging method.
        1 & 2 can be combined. 3 (as far as I know), stands alone. How are you trying to do it?
You want Params Into a Hash Called Data?
by Red Neckerson (Novice) on May 25, 2001 at 00:36 UTC
    See if this works:

    @IN = params(); foreach $field (@IN){ DATA{$field} = param($field); }

    I think this creates a hash, %DATA. So, if you have a name of "name", to get that value it's $DATA{name}. Red------

      You missed a $ off the front of $DATA{$field} which would prevent this code from compiling.

      Even with that fix, it's still a bad idea as it breaks on multi-valued CGI parameters. See (Ovid) Re(2): use CGI for more details.

      --
      <http://www.dave.org.uk>

      "Perl makes the fun jobs fun
      and the boring jobs bearable" - me

        That should be param(), not params(). Red------
Re: use CGI
by Anonymous Monk on May 24, 2001 at 22:31 UTC
    I mean.. i'm going to be having stuff come in on <STDIN> as well
Re: use CGI
by blue_cowdawg (Monsignor) on May 24, 2001 at 22:48 UTC

    Check this out:

    #!/usr/bin/perl -w ############################################################### use strict; use CGI; use Data::Dumper; my $cgi=new CGI; my $v={}; map { my($k,$vl) = ($_,$cgi->param($_)); $v->{$k}=$vl; } $cgi->param(); print Dumper($v);

    Running this a couple of different ways you get:

    [pberghol@webdev0]:[~] -$ echo " > a=foo > b=junk > c=rats > d=golf > " | perl doParse.pl (offline mode: enter name=value pairs on standard input) $VAR1 = { 'a' => 'foo', 'b' => 'junk', 'c' => 'rats', 'd' => 'golf' }; [pberghol@webdev0]:[~]
    and
    [pberghol@webdev0]:[~] -$ perl doParse.pl first=peter last=berghold hobby=cooking $VAR1 = { 'first' => 'peter', 'hobby' => 'cooking', 'last' => 'berghold' }; [pberghol@webdev0]:[~] -$

    Is this what you were after? HTH


    Peter L. BergholdSchooner Technology Consulting, Inc.
    Peter@Berghold.Netwww.berghold.net
      A reply falls below the community's threshold of quality. You may see it by logging in.