Розшифровка кодування URL-адрес (відсоткове кодування)


100

Я хочу розшифрувати кодування URL-адрес, чи є якийсь вбудований інструмент для цього чи хтось міг надати мені sedкод, який це зробить?

Я пошукав трохи через unix.stackexchange.com та в Інтернеті, але не зміг знайти жодного інструмента командного рядка для декодування кодування URL.

Що я хочу зробити, це просто змінити txtфайл так, щоб:

  • %21 стає !
  • %23 стає #
  • %24 стає $
  • %26 стає &
  • %27 стає '
  • %28 стає (
  • %29 стає )

І так далі.


Відповіді:


107

Знайшли ці вкладиші Python, які роблять те, що ви хочете:

$ 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 - звучить як новий Q для мене. Я б запитав це і посилався на це.
slm

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; в системах, де pythonза замовчуванням 3, це призведе до помилки. Зміна pythonна python2допомогу.
Іван Колмичек

4
Для цього python3можна використовувати import urllib.parse as ulзамість import urllib as ul.
ibotty

61

sed

Спробуйте наступний командний рядок:

$ 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}")

Однак вище синтаксис не буде +правильно обробляти плюси ( ), тому вам потрібно замінити їх пробілами через 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


bash + 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
}

Знайдено у файлі суті 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опція (допускає недесяткові аргументи) - це awkспеціальність GNU .
syntaxerror

Ваш перший sedкод дає мені xargs: argument line too longфайл із ≥2164 рядками.
Sparhawk

2
Ваші рішення, що стосуються printf, не враховують, що URL-адреса може містити знаки відсотків, що уникнули %25. Ви передаєте їх до printf, не уникаючи їх для printf з іншим знаком відсотка, як %%.
Джош

1
Версія bash вимагає local LC_ALL=Cвгорі, інакше всі широкі символи (наприклад, японська, китайська тощо) не будуть належним чином розбиті на байти.
Phernost


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-clientsUbuntu / 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 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 візиту
Пандія

4
Це погане рішення, оскільки воно вимагає жорсткого кодування кожного символу. Ця проблема є прикладом вашого коду, в якому відсутня часто використовувана %20послідовність втечі.
Перекрити

@Overv Я щойно переглянув
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 псевдонім у баші виглядає так:

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

Додайте косу рису в урленкод "Проба переписки" -> результат: Слэш не закодований.
Бевор

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, оскільки \xпослідовність виходу не визначена в Posix.


Ласкаво просимо до U&L. Можливо, ви могли б пояснити цю відповідь і як вона працює. Як правило, наші відповіді віддають перевагу довгій формі з деталями, а не лише фрагментами коду.
slm

Мені дуже подобається ця відповідь, тому що вона є всеосяжною, портативною і не вимагає додаткових важчих зовнішніх програм, таких як perl або python. Добре працює для мене.
Стів Віллз

1
Прекрасне рішення. І ще коротше і розумніші: ... | sed 's/+/ /g;s/%\(..\)/\\\\x\1/g'. -eОпція може бути опущено насправді ...
SyntaxError

1
@josch Ви маєте рацію, printfце вбудований dashі він не розпізнає \xвтечу. Ви можете використовувати /usr/bin/printfзамість printfтого, щоб змусити його працювати. Зазвичай ви повинні вміти користуватися command printf, але, здається, це не працює як слід. Він продовжує використовувати вбудований.
Jérôme Pouiller

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

1

Тільки оболонка:

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

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

У zsh ${x//%/a}додає aдо кінця, але ${x//\%/a}замінює %на a.


1

Ось відповідні біти з іншого сценарію (що я просто безсоромно вкрав із мого сценарію завантаження з youtube.com з іншої відповіді), про який я писав раніше. Він використовує sedі оболонку для створення робочого urldecode.

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

Я не клянусь, що вона є всеосяжною - і насправді я сумніваюсь у цьому - але це, безумовно, обробляє ютуб.



0

Ще одне рішення з використанням рубіну (прийнята відповідь 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.