Мне нужно обработать кодирование и декодирование URI (т.е. процент) в моем Perl-скрипте. Как мне это сделать?
Это вопрос от официального perlfaq. Мы импортируем perlfaq в Stack Overflow.
Мне нужно обработать кодирование и декодирование URI (т.е. процент) в моем Perl-скрипте. Как мне это сделать?
Это вопрос от официального perlfaq. Мы импортируем perlfaq в Stack Overflow.
Это официальный ответ на часто задаваемые вопросы без последующих правок.
Эти %
кодировки обрабатывают зарезервированные символы в 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;
Кодирование своими руками (улучшенная версия выше):
$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;
Кодеры помогают кодерам - обмен знаниями!
Возможно, это поможет определиться с выбором метода.
Тесты на 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% --