Как с помощью Perl декодировать или создавать эти% -кодировки в Интернете?

Мне нужно обработать кодирование и декодирование URI (т.е. процент) в моем Perl-скрипте. Как мне это сделать?


Это вопрос от официального perlfaq. Мы импортируем perlfaq в Stack Overflow.


person perlfaq    schedule 22.12.2010    source источник


Ответы (3)


Это официальный ответ на часто задаваемые вопросы без последующих правок.

Эти % кодировки обрабатывают зарезервированные символы в URI, как описано в RFC 2396, раздел 2. Эта кодировка заменяет зарезервированный символ шестнадцатеричным представлением номера символа из таблицы US-ASCII. Например, двоеточие : становится %3A.

В сценариях CGI вам не нужно беспокоиться о декодировании URI, если вы используете CGI.pm . Вам не нужно обрабатывать URI самостоятельно ни при входе, ни при выходе.

Если вам нужно кодировать строку самостоятельно, помните, что вы никогда не должны пытаться кодировать уже составленный URI. Вам нужно экранировать компоненты по отдельности, а затем собрать их вместе. Чтобы закодировать строку, вы можете использовать модуль URI :: Escape. Функция uri_escape возвращает экранированную строку:

my $original = "Colon : Hash # Percent %";

my $escaped = uri_escape( $original );

print "$escaped\n"; # 'Colon%20%3A%20Hash%20%23%20Percent%20%25'

Чтобы декодировать строку, используйте функцию uri_unescape:

my $unescaped = uri_unescape( $escaped );

print $unescaped; # back to original

Если вы хотели сделать это самостоятельно, вам просто нужно заменить зарезервированные символы на их кодировки. Глобальная замена - это один из способов сделать это:

# encode
$string =~ s/([^^A-Za-z0-9\-_.!~*'()])/ sprintf "%%%0x", ord $1 /eg;

#decode
$string =~ s/%([A-Fa-f\d]{2})/chr hex $1/eg;
person Community    schedule 22.12.2010
comment
У Марка Стосберга есть соответствующая запись в блоге: mark. stosberg.com/blog/2010/12/ по теме. - person Sinan Ünür; 22.12.2010

Кодирование своими руками (улучшенная версия выше):

$string =~ s/([^^A-Za-z0-9\-_.!~*'()])/ sprintf "%%%02x", ord $1 /eg;

(обратите внимание на "% 02x", а не только на "% 0x")

Декодирование своими руками (добавление '+' -> ''):

$string =~ s/\+/ /g; $string =~ s/%([A-Fa-f\d]{2})/chr hex $1/eg;

Кодеры помогают кодерам - обмен знаниями!

person Joseph Martin    schedule 12.11.2015

Возможно, это поможет определиться с выбором метода.

Тесты на perl 5.22.1. Каждая функция возвращает одинаковый результат для заданного $string.

Код:

#!/usr/bin/env perl

my $string = "ala ma 0,5 litra 40%'owej vodki :)";

use Net::Curl::Easy;
my $easy = Net::Curl::Easy->new();
use URI::Encode qw( uri_encode );
use URI::Escape qw( uri_escape );
use Benchmark(cmpthese);

cmpthese(10_000, {
    'a' => sub {
        $string =~ s/([^^A-Za-z0-9\-_.!~*'()])/ sprintf "%%%0x", ord $1 /eg;
    },
    'b' => sub {
        $easy->escape( $string );
    },
    'c' => sub {
        uri_encode( $string, {encode_reserved => 1} ); 
    },
    'd' => sub {
        uri_escape( $string );
    },
});

И результаты:

    Rate    c    d    a    b
c  457/s   -- -33% -65% -89%
d  680/s  49%   -- -48% -84%
a 1307/s 186%  92%   -- -69%
b 4237/s 826% 523% 224%   --
person alan    schedule 30.04.2016
comment
С этим тестом есть серьезная проблема: каждая итерация изменяет глобальную строку $, делая больше работы для следующей итерации. Значит, у «а» и «б» меньше работы, чем у «в» и «г». Попробуйте напечатать длину ($ string) после выполнения cmpthese (). - person TheAmigo; 07.04.2017