Декодирование URL-кодировки (процентное кодирование)


101

Я хочу расшифровать кодировку URL-адреса, есть ли встроенный инструмент для этого или кто-нибудь может предоставить мне sedкод, который это сделает?

Я немного поискал на unix.stackexchange.com и в Интернете, но не смог найти инструмента командной строки для декодирования кодировки URL.

Я хочу просто отредактировать txtфайл так, чтобы:

  • %21 становится !
  • %23 становится #
  • %24 становится $
  • %26 становится &
  • %27 становится '
  • %28 становится (
  • %29 становится )

И так далее.


Ответы:


107

Нашли эти лайнеры Python one, которые делают то, что вы хотите:

$ alias urldecode='python -c "import sys, urllib as ul; \
    print ul.unquote_plus(sys.argv[1])"'

$ alias urlencode='python -c "import sys, urllib as ul; \
    print ul.quote_plus(sys.argv[1])"'

пример

$ urldecode 'q+werty%3D%2F%3B'
q werty=/;

$ urlencode 'q werty=/;'
q+werty%3D%2F%3B

Рекомендации


Я знаю это очень поздно, но есть ли способ сделать это с помощью редактирования на месте?
DisplayName

@DisplayName - звучит как новый вопрос для меня. Я бы спросил, и сослаться на это.
СЛМ

15
потоковая передача:cat your_lovely_file.csv| python -c "import sys, urllib as ul; [sys.stdout.write(ul.quote_plus(l)) for l in sys.stdin]"
kirill_igum

5
Обратите внимание, что это Python 2; в системах с python3 по умолчанию это приведет к ошибке. Меняется pythonна python2помощь.
Иван Колмычек

4
Ибо python3можно использовать import urllib.parse as ulвместо import urllib as ul.
ibotty

61

СЕПГ

Попробуйте следующую командную строку:

$ sed 's@+@ @g;s@%@\\x@g' file | xargs -0 printf "%b"

или следующий вариант использования echo -e:

$ sed -e's/%\([0-9A-F][0-9A-F]\)/\\\\\x\1/g' file | xargs echo -e

Примечание. Приведенный выше синтаксис может не преобразовываться +в пробелы и может использовать все символы новой строки.


Вы можете определить его как псевдоним и добавить его в rc- файлы вашей оболочки :

$ alias urldecode='sed "s@+@ @g;s@%@\\\\x@g" | xargs -0 printf "%b"'

Тогда каждый раз, когда вам это нужно, просто идите с:

$ echo "http%3A%2F%2Fwww" | urldecode
http://www

удар

При создании сценариев вы можете использовать следующий синтаксис:

input="http%3A%2F%2Fwww"
decoded=$(printf '%b' "${input//%/\\x}")

Однако приведенный выше синтаксис не будет +правильно обрабатывать pluses ( ), поэтому вы должны заменить их пробелами через sed.

Вы также можете использовать следующую urlencode()и urldecode()функцию:

urlencode() {
    # urlencode <string>
    local length="${#1}"
    for (( i = 0; i < length; i++ )); do
        local c="${1:i:1}"
        case $c in
            [a-zA-Z0-9.~_-]) printf "$c" ;;
            *) printf '%%%02X' "'$c" ;;
        esac
    done
}

urldecode() {
    # urldecode <string>

    local url_encoded="${1//+/ }"
    printf '%b' "${url_encoded//%/\\x}"
}

Обратите внимание, что выше urldecode()предполагается, что данные не содержат обратной косой черты.

Вот аналогичная версия Джоэла, найденная по адресу: https://github.com/sixarm/urldecode.sh


Баш + XXD

Функция Bash с xxdинструментом:

urlencode() {
  local length="${#1}"
  for (( i = 0; i < length; i++ )); do
    local c="${1:i:1}"
    case $c in
      [a-zA-Z0-9.~_-]) printf "$c" ;;
    *) printf "$c" | xxd -p -c1 | while read x;do printf "%%%s" "$x";done
  esac
done
}

Находится в gist-файле cdown , также в stackoverflow .


PHP

Используя PHP, вы можете попробовать следующую команду:

$ echo oil+and+gas | php -r 'echo urldecode(fgets(STDIN));' // Or: php://stdin
oil and gas

или просто:

php -r 'echo urldecode("oil+and+gas");'

Используйте -Rдля многострочного ввода.


Perl

В Perl вы можете использовать URI::Escape.

decoded_url=$(perl -MURI::Escape -e 'print uri_unescape($ARGV[0])' "$encoded_url")

Или обработать файл:

perl -i -MURI::Escape -e 'print uri_unescape($ARGV[0])' file

AWK

Попробуйте другое решение:

awk -niord '{printf RT?$0chr("0x"substr(RT,2)):$0}' RS=%..

Примечание. Параметр -nотносится к GNU awk.

Смотрите: Использование awk printf для urldecode текста .

расшифровка имен файлов

Если вам нужно удалить кодировку URL из имен файлов, используйте deurlnameинструмент из renameutils(например deurlname *.*).

Смотрите также:


Связанный:


1
awk: Поскольку здесь используется библиотечная функция, chr()существует высокая вероятность того, что она будет работать исключительно на GNU awk ( gawk). Однако, в этом случае вряд ли будет какой - либо эквивалент для POSIX awk, так как -nвариант ( с учетом не десятичных аргументов) IS гну awkспециальности.
syntaxerror

Ваш первый sedкод дает мне xargs: argument line too longфайл с ≥2164 строками.
Sparhawk

2
Ваши решения, связанные с printfэтим, не учитывают, что URL может содержать экранированные знаки процента, например %25. Вы передаете их в printf, не экранируя их для printf с другим знаком процента, например %%.
Йош

1
Версия bash требуется local LC_ALL=Cвверху, иначе все широкие символы (например, японский, китайский и т. Д.) Не будут правильно разбиты на байты.
Черность


18

Для этого есть встроенная функция в стандартной библиотеке Python. В Python 2 это так urllib.unquote.

decoded_url=$(python2 -c 'import sys, urllib; print urllib.unquote(sys.argv[1])' "$encoded_url")

Или обработать файл:

python2 -c 'import sys, urllib; print urllib.unquote(sys.stdin.read())' <file >file.new &&
mv -f file.new file

В Python 3 это так urllib.parse.unquote.

decoded_url=$(python3 -c 'import sys, urllib.parse; print(urllib.parse.unquote(sys.argv[1]))' "$encoded_url")

Или обработать файл:

python3 -c 'import sys, urllib; print(urllib.parse.unquote(sys.stdin.read()))' <file >file.new &&
mv -f file.new file

В Perl вы можете использовать URI::Escape.

decoded_url=$(perl -MURI::Escape -e 'print uri_unescape($ARGV[0])' "$encoded_url")

Или обработать файл:

perl -i -MURI::Escape -e 'print uri_unescape($ARGV[0])' file

Если вы хотите придерживаться переносимых инструментов POSIX, это неловко, потому что единственным серьезным кандидатом является awk, который не разбирает шестнадцатеричные числа. См. Использование awk printf для urldecode текста для примеров с общими реализациями awk, включая BusyBox.


10

Если вы хотите использовать простую sedкоманду, то используйте следующее:

sed -e 's/%21/!/g' -e 's/%23/#/g' -e 's/%24/$/g' -e 's/%26/\&/g' -e "s/%27/'/g" -e 's/%28/(/g' -e 's/%29/)/g'

Но удобнее создать скрипт вроде sedscript:

s/%21/!/g
s/%23/#/g
s/%24/$/g
s/%26/\&/g
s/%27/'/g
s/%28/(/g
s/%29/)/g

Затем запустите sed -f sedscript < old > new, который будет выводить по вашему желанию.


Для удобства команда urlencodeтакже доступна непосредственно в gridsite-clientsпакете, из которого она может быть установлена ​​( sudo apt-get install gridsite-clientsв системе Ubuntu / Debian).

ИМЯ

    urlencode - конвертирует строки в или из URL-кодированной формы
СИНТАКСИС

    urlencode [-m|-d] string [string ...]

ОПИСАНИЕ

    urlencode кодирует строки в соответствии с RFC 1738.

    То есть символы A- Z a- z 0- 9 . _и -передаются через неизмененные, но все остальные символы представлены в виде% HH, где HH - их шестнадцатеричное ASCII-представление в верхнем регистре. Например, URL http://www.gridpp.ac.uk/становитсяhttp%3A%2F%2Fwww.gridpp.ac.uk%2F

    urlencodeпреобразует каждый символ во все строки, указанные в командной строке. Если задано несколько строк, они преобразуются с разделительными пробелами перед преобразованием.

ПАРАМЕТРЫ
    -m
      Вместо полного преобразования, сделайте GridSite "мягкое кодирование URL", в котором AZ 0-9. = - _ @ и / передаются без изменений. Это приводит к чуть более понятным для человека строкам, но приложение должно быть готово для создания или имитации каталогов, подразумеваемых любыми слешами.
    -d
      Делайте URL-декодирование, а не кодирование, согласно RFC 1738. Строки% HH и% hh преобразуются, а другие символы передаются через неизмененные, за исключением того, что +преобразуется в пробел.

Пример декодирования URL:

$ urlencode -d "http%3a%2f%2funix.stackexchange.com%2f"
http://unix.stackexchange.com/

$ urlencode -d "Example: %21, %22, . . . , %29 etc"
Example: !, ", . . . , ) etc

Для учебника в sed гостях
Pandya

4
Это плохое решение, потому что оно требует жесткого кодирования каждого символа. Эта проблема иллюстрируется тем, что в вашем коде отсутствует часто используемая %20escape-последовательность.
Овер

@ Overver, я только что пересмотрел
Pandya

Кроме того, вы можете перепроверить, что s/%26/&/gделает. (Я исправил это.)
G-Man

9

Perl один лайнер:

$ perl -pe 's/\%(\w\w)/chr hex $1/ge'

Пример:

$ echo '%21%22' |  perl -pe 's/\%(\w\w)/chr hex $1/ge'
!"

1
Этот ответ привлекателен, когда вы не хотите заниматься установкой модулей Perl.
Шридхар Сарнобат

1
Только тот, который работал элегантно для меня на MacOS.
Qix


7

Я не могу комментировать лучший ответ в этой теме , так что вот мой.

Лично я использую эти псевдонимы для кодирования и декодирования URL:

alias urlencode='python -c "import urllib, sys; print urllib.quote(  sys.argv[1] if len(sys.argv) > 1 else sys.stdin.read()[0:-1])"'

alias urldecode='python -c "import urllib, sys; print urllib.unquote(sys.argv[1] if len(sys.argv) > 1 else sys.stdin.read()[0:-1])"'

Обе команды позволяют вам преобразовывать данные, передаваемые в качестве аргумента командной строки, или читать их из стандартного ввода , поскольку обе строки указывают на наличие аргументов командной строки (даже пустых) и обрабатывают их или просто читают стандартный ввод в противном случае.


обновление 2017-05-23 (косая черта)

В ответ на комментарий @ Bevor.

Если вам также необходимо кодировать косую черту, просто добавьте второй пустой аргумент в функцию кавычек, тогда косая черта также будет закодирована.

Итак, наконец, urlencode псевдоним в bash выглядит так:

alias urlencode='python -c "import urllib, sys; print urllib.quote(sys.argv[1] if len(sys.argv) > 1 else sys.stdin.read()[0:-1], \"\")"'

пример

$ urlencode "Проба пера/Pen test"
%D0%9F%D1%80%D0%BE%D0%B1%D0%B0%20%D0%BF%D0%B5%D1%80%D0%B0%2FPen%20test

$ echo "Проба пера/Pen test" | urlencode
%D0%9F%D1%80%D0%BE%D0%B1%D0%B0%20%D0%BF%D0%B5%D1%80%D0%B0%2FPen%20test

$ urldecode %D0%9F%D1%80%D0%BE%D0%B1%D0%B0%20%D0%BF%D0%B5%D1%80%D0%B0%2FPen%20test
Проба пера/Pen test

$ echo "%D0%9F%D1%80%D0%BE%D0%B1%D0%B0%20%D0%BF%D0%B5%D1%80%D0%B0%2FPen%20test" | urldecode
Проба пера/Pen test

$ urlencode "Проба пера/Pen test" | urldecode
Проба пера/Pen test

$ echo "Проба пера/Pen test" | urlencode | urldecode
Проба пера/Pen test

1
Не кодирует косые черты.
бувигер

@Bevor: пример?
DIG mbl

Добавьте косую черту в urlencode "Проба пера" -> результат: косая черта не закодирована.
бувигер

1
@Bevor: Вы правы. Спасибо за ваш комментарий. Я также изменю свой ответ, чтобы отразить в нем ваш комментарий.
DIG mbl

4

И еще один подход Perl:

#!/usr/bin/env perl
use URI::Encode;
my $uri     = URI::Encode->new( { encode_reserved => 0 } );
while (<>) {

    print $uri->decode($_)
}

Вам нужно будет установить URI::Encodeмодуль. На моем Debian я мог просто запустить

sudo apt-get install liburi-encode-perl

Затем я запустил скрипт выше для тестового файла, содержащего:

http://foo%21asd%23asd%24%26asd%27asd%28asd%29

Результат был (я сохранил сценарий как foo.pl):

$ ./foo.pl
http://foo!asd#asd$&asd'asd(asd)

3

Ответ в (в основном Posix) оболочке:

$ input='%21%22'
$ printf "`printf "%s\n" "$input" | sed -e 's/+/ /g' -e 's/%\(..\)/\\\\x\1/g'`"
!"

Объяснение:

  • -e 's/+/ /gпреобразует каждый +в пространство (как описано в норме кодирования URL)
  • -e 's/%\(..\)/\\\\x\1/g'преобразовать каждый %XXв \\xXX. Обратите внимание, что одно из них \будет удалено правилами цитирования.
  • Внутренний printf только для передачи ввода в sed. Мы можем заменить его любым другим механизмом
  • Внешний printf интерпретирует \\xXXпоследовательности и отображает результат.

Редактировать:

Так как %всегда должен интерпретироваться в URL, можно упростить этот ответ. В оном, я думаю , что это уборщик использовать xargsвместо обратных кавычек (благодаря @josch).

$ input='%21%22+%25'
$ printf "%s\n" "$input" | sed -e 's/+/ /g; s/%/\\x/g' | xargs -0 printf
!" %

К сожалению, (как заметил @josch) ни одно из этих решений не является Posix-совместимым, поскольку \xescape-последовательность не определена в Posix.


Добро пожаловать в U & L. Возможно, вы могли бы объяснить этот ответ и как он работает. Обычно мы предпочитаем, чтобы наши ответы были подробными, а не просто фрагментами кода.
СЛМ

Мне очень нравится этот ответ, потому что он всеобъемлющий, переносимый и не требует дополнительных более тяжелых внешних программ, таких как perl или python. Хорошо работает для меня.
Стив Уиллс

1
Отличное решение. И еще короче и умнее ... | sed 's/+/ /g;s/%\(..\)/\\\\x\1/g'. Эта -eопция может быть опущена здесь на самом деле ...
syntaxerror

1
@josch Вы правы, printfон встроен dashи не распознает \xвыход. Вы можете использовать /usr/bin/printfвместо printfтого, чтобы заставить его работать. Как правило, вы должны быть в состоянии использовать command printf, но, похоже, не работает как следует. Продолжайте использовать встроенный.
Жером Пуйлер

1
@Jezz, действительно, поддержка \xэкранирования не является частью POSIX: pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html Во время моих тестов я обнаружил еще одну проблему. Возможно, вы захотите заменить свое ..регулярное выражение, [a-zA-Z0-9][a-zA-Z0-9]потому что в противном случае ввод, такой как «%%%», завершится неудачно. Я также добавил s/%/%%/gв конце, чтобы убедиться, что экранирование процентов для printf.
июня

1

Shell только:

$ x='a%20%25%e3%81%82';printf "${x//\%/\\x}"
a %あ

Добавьте --или, %bчтобы аргументы, начинающиеся с тире, не рассматривались как параметры.

В zsh ${x//%/a}добавляет aв конец, но ${x//\%/a}заменяет %на a.


1

Вот соответствующие биты из другого скрипта (который я просто бесстыдно украл из моего скрипта загрузки youtube.com из другого ответа), который я написал ранее. Он использует sedи оболочку для создания рабочего URL-кода.

set \! \" \# \$ \% \& \' \( \) \* \ \+ \, \/ \: \; \= \? \@ \[ \]
for c do set "$@" "'$c" "$c"; shift; done
curl -s "$url" | sed 's/\\u0026/\&/g;'"$(
    printf 's/%%%X/\\%s/g;' "$@"
)"

Я не буду клясться, что он всеобъемлющий - и на самом деле я в этом сомневаюсь - но он, безусловно, справился с YouTube.


1

Вот функция BASH, чтобы сделать именно это:

function urldecode() {
        echo -ne $(echo -n "$1" | sed -E "s/%/\\\\x/g")
}

работает как очарование
AbdElraouf Sabri

0

Другое решение, использующее ruby ​​(принятый ответ python не работал для меня)

alias urldecode='ruby -e "require \"cgi\"; puts CGI.unescape(ARGV[0])"'
alias urlencode='ruby -e "require \"cgi\"; puts CGI.escape(ARGV[0])"'

пример

$ urldecode 'q+werty%3D%2F%3B'
q werty=/;

$ urlencode 'q werty=/;'
q+werty%3D%2F%3B
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.