http://www.perlmonks.org?node_id=69065

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

I have text that I want to escape, so to put it into a URL Query String. The current regex I am using is:

$url_text =~ s/([^;\/?:@&=+\$,A-Za-z0-9\-_.!~*'()])/sprintf("%%%02X", ord($1))/g;

In theory, yippee, it should work, in a perfect world, but what I get in return is my string with the character that is supposed to be escaped with sprintf("%%%02X", ord( ))... Why is this happening?

"The pajamas do not like to eat large carnivore toasters."
In German: "Die Pyjamas mögen nicht große Tiertoaster essen.
In Spanish: "Los pijamas no tienen gusto de comer las tostadoras grandes del carnívoro."

Replies are listed 'Best First'.
Re: URL escaping
by arturo (Vicar) on Apr 02, 2001 at 21:32 UTC

    Use URI::Escape or CGI's built-in escape function to do this.

    use CGI; my $q = CGI->new(); my $string = "What a lovely function!"; $string = $q->escape($string); # or using the procedural interface... use CGI qw(:param); my $string = "What a lovely function!"; $string = CGI::escape($string);

    HTH </code>

    Philosophy can be made out of anything. Or less -- Jerry A. Fodor

Re: URL escaping
by dws (Chancellor) on Apr 02, 2001 at 21:35 UTC
    CGI.pm is your friend.
    use CGI; ... $url_escaped = CGI::escape($url_text);


    (Thanks to arturo for catching a freudian typo.)

Re: URL escaping
by Masem (Monsignor) on Apr 02, 2001 at 21:26 UTC
    The regex is not recognizing the sprintf as a function in the second part of the s/// operator, so it's probably better (and more legit) to break this into two lines:
    if ($url_text =~ m/([^;\/?:@&=+\$,A-Za-z0-9\-_.!~*'()])/ ) { $url_sub = sprintf( "%%%02X", ord( $1 ) ); $url_text =~ s/([^;\/?:@&=+\$,A-Za-z0-9\-_.!~*'()])/$url_sub/; }

    Update Or , duh, use the s///e modifier (stupid me...)

    $url_text =~ s/([^;\/?:@&=+\$,A-Za-z0-9\-_.!~*'()])/sprintf( "%%%02X", + ord( $1 ) )/ge;
    What I have above won't catch multiple URLs on the same line.
    Dr. Michael K. Neylon - mneylon-pm@masemware.com || "You've left the lens cap of your mind on again, Pinky" - The Brain
Re: URL escaping
by suaveant (Parson) on Apr 02, 2001 at 23:24 UTC
    I use the following
    sub encode { $_ = join '', @_; s/(\W)/'%'.sprintf("%02lx",ord($1))/ge; return $_; } sub decode { $_ = join '', @_; s/%([a-fA-F\d][a-fA-F\d])/chr(hex($1))/ge; return $_; }
    Works for me
                    - Ant
Re: URL escaping
by knobunc (Pilgrim) on Apr 03, 2001 at 16:55 UTC

    Along with all the other suggested modules you can use Apache::Util::escape_uri if you are using mod_perl. The perldoc says that the Apache version is about 3 times faster. Also if you need to escape HTML there is a escape_html subroutine in the module that is much faster than HTML::Entities::encode.

    -ben