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

I'm porting some older C software to an interim interface with perl as a go-between, and I'm hoping that much of what I need to do can be handled with existing modules.

my script will be called through the linux env command, which sets environment variables, then applies them to the script:

env REQUEST_METHOD=GET DATA_SOURCE=cmdline QUERY_STRING=DBNAME=mydatab +ase+SF=dbfield+SV="search_string"+HEAD=none+TAIL=none+TEMPLATE_DIR=te +mplates/path/+CONTENT_TYPE=none /home/evan/test.pl
so these are then accessible in perl through the %ENV hash. the important one here is $ENV{QUERY_STRING}, because I'd like to parse it with the CGI module, but because its delimited with plus signs instead of ampersands, CGI doesnt seem to like that. it stores it all as one name=value pair (interpreting the + delimiters as spaces):
use CGI; use Data::Dumper; my $q = new CGI( $ENV{QUERY_STRING} ); print Dumper( $q->param('DBNAME') ); # this outputs: $VAR1 = 'mydatabase SF=dbfield SV="search_string" HEAD=none TAIL=none +TEMPLATE_DIR=templates/path/ CONTENT_TYPE=none';
so, my question (for now) is, can I tell CGI to interpret this string as not URL-encoded, and to use the + as a delimiter? or is there a Better Way?

Edited by davorg: Fixed code tags to allow line to split

Replies are listed 'Best First'.
Re: using CGI with different delimiter than '&'
by davorg (Chancellor) on Jul 20, 2006 at 14:46 UTC

    What you have isn't a valid CGI parameter string. Therefore you can't really expect CGI.pm to be able to parse it. You'll have to write your own parser.

    Not that that's going to be very difficult. On your example data, the following seems to work fine:

    my %params = split /[+=]/, $ENV{QUERY_STRING}; print Dumper(\%params);

    Update: The new examples that you've added won't work with my simple parser above. But this slightly more complex version seems to work:

    use Data::Dumper; use Text::ParseWords; $ENV{QUERY_STRING} = 'DATABASE=inventory+SF=name\&title+param3="3+4"'; my %params = map { split /=/, $_, 2 } parse_line('\+', 0, $ENV{QUERY_S +TRING}); print Dumper(\%params);
    --
    <http://dave.org.uk>

    "The first rule of Perl club is you do not talk about Perl club."
    -- Chip Salzenberg

Re: using CGI with different delimiter than '&'
by wazoox (Prior) on Jul 20, 2006 at 15:15 UTC
    You may use semicolons as sepators instead of ampersands, according to CGI.pm documentation :
    -newstyle_urls
    Separate the name=value pairs in CGI parameter query strings with semicolons rather than ampersands. For example:
    ?name=fred;age=24;favorite_color=3
Re: using CGI with different delimiter than '&'
by duff (Parson) on Jul 20, 2006 at 15:59 UTC

    A better way might be to substitute all of the + in $ENV{QUERY_STRING} with & and then call CGI. (I'm assuming you can rely on the + to always be a separator)

    $ENV{QUERY_STRING} =~ s/\+/&/g;
      yes, but that wouldnt work with the second example the OP provided (in a reply), where it may have + within quoted strings.

      davorg's solution with Text::ParseWords ought to work though.

      __________
      Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.
      - Terry Pratchett

Re: using CGI with different delimiter than '&'
by Anonymous Monk on Jul 20, 2006 at 14:46 UTC
    i forgot some vital points:
    • the values may contain +'s enclosed in quotes
    • the values may contain &'s
    for instance, this literal string:
    DATABASE=inventory+SF=name\&title+param3="3+4"
    should evaluate to this name=value pair:
    DATABASE = "inventory" SF = "name\&title" param3 = "3+4"