Have you wished for Javascript escape()-style function in Perl? Perl has, by default, all sorts of cool escape functions, but regrettably none for specifically handling URIs.

Regrettably, writing one is not easy in Perl (tr/// doesn't do multi-byte and "smart" stuff), but it's entirely possible and everyone can do that in one sitting...

For The Rest Of Us

Of course, there's a CPAN module URI for this (in Debian, last time I checked, it's in liburi-perl package and it's dependant for LWP, a cool module everyone should have =) Its canonical function is extremely handy.

Regrettably this method translates spaces to %20, which is overkill. (The Standard says you can always use +'es instead of %20...)

      $escaped = URI->new($url)->canonical->as_string;

But... what to do if we don't want to use that module???

The Boring Way

This is the iterative approach. It just takes the string character by character; if character is not alphanumeric, it will be escaped before it's added to result string. (This uses POSIX module, though it wouldn't need to).

sub quote {
  my $str = shift || die "Some coder used quote() with no args. Fool.\n";
  my $newstr;

  $str =~ tr/ /+/; # Convert spaces to +'es
  # Iterate over characters; If it's alphanumeric (or plus), use it
  # as it is, else insert it as a %XX hex escape.
  for(my $n = 0; $n < length($str); $n++) {
    my $char = substr($str,$n,1);
    if($char eq '+' or POSIX::isalnum($char)) {
      $newstr .= $char;
    } else {
      $newstr .= "%" . uc sprintf("%02x",ord($char));
    }
  }

  return $newstr;
}

The Kewl Way

TIMTOWTDI - this one uses map { ... } function, which looks hairier and is thus infinitely cooler.

sub quote ($) {
  my $str = shift || die "Some coder used quote() with no args. Fool.\n";

  $str =~ tr/ /+/;
  return join "", map {
    if(tr/a-zA-Z+// == 0) {
      $_ = "%" . uc sprintf("%02x",ord);
    } else {
      $_ = $_;
    }
  } split //, $str;
}

(Thought-job of the day: Figure out what kind of stuff return, join, map, and split do here. Spoiler: We split the array with split, then map each character to the quoted/unquoted character, and then join our return value. =)

Log in or register to write something here or to contact authors.