Pengodean URL decoding (pengodean persen)


100

Saya ingin mendekodekan penyandian URL, apakah ada alat bawaan untuk melakukan ini atau ada yang bisa memberi saya sedkode yang akan melakukan ini?

Saya memang mencari sedikit melalui unix.stackexchange.com dan di internet tetapi saya tidak dapat menemukan alat baris perintah untuk decoding encoding url.

Yang ingin saya lakukan hanyalah mengedit txtfile sehingga:

  • %21 menjadi !
  • %23 menjadi #
  • %24 menjadi $
  • %26 menjadi &
  • %27 menjadi '
  • %28 menjadi (
  • %29 menjadi )

Dan seterusnya.


Jawaban:


107

Temukan Python one liners ini yang melakukan apa yang Anda inginkan:

$ 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])"'

Contoh

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

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

Referensi


Saya tahu ini sangat terlambat, tetapi apakah ada cara saya bisa melakukan ini dengan mengedit di tempat?
DisplayName

@DisplayName - terdengar seperti Q baru bagi saya. Saya akan bertanya, dan referensi yang satu ini.
slm

15
streaming: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
Perhatikan, bahwa ini adalah Python 2; pada sistem di mana python3 secara default, ini akan menghasilkan kesalahan. Mengubah pythonuntuk python2membantu.
Ivan Kolmychek

4
Untuk python3Anda dapat menggunakan import urllib.parse as ulsebagai gantinya import urllib as ul.
ibotty

61

sed

Coba baris perintah berikut:

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

atau alternatif berikut menggunakan echo -e:

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

Catatan: Sintaks di atas mungkin tidak dikonversi +ke spasi, dan dapat memakan semua baris baru.


Anda dapat mendefinisikannya sebagai alias dan menambahkannya ke file rc shell Anda :

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

Lalu setiap kali Anda membutuhkannya, cukup ikuti:

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

Pesta

Saat membuat skrip, Anda dapat menggunakan sintaks berikut:

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

Namun sintaks di atas tidak akan menangani plus ( +) dengan benar, jadi Anda harus menggantinya dengan spasi via sed.

Anda juga dapat menggunakan fungsi urlencode()dan berikut ini 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}"
}

Perhatikan bahwa di atas urldecode()mengasumsikan data tidak mengandung garis miring terbalik.

Berikut ini adalah versi Joel serupa yang ditemukan di: https://github.com/sixarm/urldecode.sh


bash + xxd

Fungsi Bash dengan xxdalat:

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
}

Ditemukan di file inti cdown , juga di stackoverflow .


PHP

Menggunakan PHP Anda dapat mencoba perintah berikut:

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

atau hanya:

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

Gunakan -Runtuk input baris ganda.


Perl

Di Perl Anda dapat menggunakan URI::Escape.

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

Atau untuk memproses file:

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

awk

Coba solusi anon :

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

Catatan: Parameter -nkhusus untuk GNU awk.

Lihat: Menggunakan awk printf untuk urldecode teks .

nama file decoding

Jika Anda perlu menghapus penyandian url dari nama file, gunakan deurlnamealat dari renameutils(mis deurlname *.*.).

Lihat juga:


Terkait:


1
awk: Karena ini menggunakan fungsi perpustakaan chr(),, ada kemungkinan besar itu hanya akan berfungsi pada GNU awk ( gawk). Namun, dalam kasus ini hampir tidak ada yang setara untuk POSIX awk, karena -nopsi (memungkinkan argumen non-desimal) ADALAHawk spesialisasi GNU .
syntaxerror

sedKode pertama Anda memberi saya xargs: argument line too longfile dengan ≥2164 baris.
Sparhawk

2
Solusi Anda yang melibatkan printftidak memperhitungkan bahwa url mungkin mengandung tanda persentase yang lolos seperti %25. Anda meneruskan ini ke printf tanpa melarikan mereka untuk printf dengan tanda persentase lain seperti %%.
josch

1
Versi bash membutuhkan local LC_ALL=Cdi bagian atas, jika tidak semua karakter lebar (yaitu Jepang, Cina, dll.) Tidak benar-benar dipecah menjadi byte.
Phernost


18

Ada fungsi bawaan untuk itu di pustaka standar Python. Dalam Python 2, itu urllib.unquote.

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

Atau untuk memproses file:

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

Dalam Python 3, itu urllib.parse.unquote.

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

Atau untuk memproses file:

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

Di Perl Anda dapat menggunakan URI::Escape.

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

Atau untuk memproses file:

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

Jika Anda ingin tetap menggunakan alat portabel POSIX, itu aneh, karena satu-satunya kandidat yang serius adalah awk, yang tidak menguraikan angka heksadesimal. Lihat Menggunakan awk printf ke urldecode teks untuk contoh dengan implementasi awk yang umum, termasuk BusyBox.


10

Jika Anda ingin menggunakan sedperintah yang berpikiran sederhana , maka gunakan yang berikut ini:

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'

Tetapi lebih mudah untuk membuat skrip seperti (katakanlah sedscript):

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

Kemudian jalankan sed -f sedscript < old > new, yang akan menampilkan seperti yang Anda inginkan.


Untuk kemudahan, perintah urlencodeini juga tersedia langsung dalam gridsite-clientspaket yang dapat diinstal dari (oleh sudo apt-get install gridsite-clientsdalam sistem Ubuntu / Debian).

NAMA

    urlencode - mengonversi string ke atau dari formulir yang disandikan URL
RINGKASAN

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

DESKRIPSI

    urlencode mengkodekan string menurut RFC 1738.

    Yaitu, karakter A- Z a- z 0- 9 . _dan -dilewatkan melalui yang tidak dimodifikasi, tetapi semua karakter lain direpresentasikan sebagai% HH, di mana HH adalah dua digit representasi ASCII heksadesimal huruf besar mereka. Misalnya, URL http://www.gridpp.ac.uk/menjadihttp%3A%2F%2Fwww.gridpp.ac.uk%2F

    urlencodemengkonversi setiap karakter di semua string yang diberikan pada baris perintah. Jika beberapa string diberikan, mereka digabungkan dengan memisahkan ruang sebelum konversi.

PILIHAN
    -m
      Alih-alih konversi penuh, lakukan GridSite "pengkodean URL ringan" di mana AZ az 0-9. = - _ @ dan / dilewati tanpa dimodifikasi. Ini menghasilkan string yang sedikit lebih dapat dibaca manusia tetapi aplikasi harus siap untuk membuat atau mensimulasikan direktori yang tersirat oleh garis miring.
    -d
      Lakukan URL-decoding daripada encoding, menurut RFC 1738.% HH dan% hh string dikonversi dan karakter lain dilewatkan tanpa dimodifikasi, dengan pengecualian yang +dikonversi ke ruang.

Contoh URL penguraian:

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

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

Untuk tutorial tentang sed kunjungan
Pandya

4
Ini adalah solusi yang buruk, karena itu membutuhkan hardcoding setiap karakter. Masalah ini dicontohkan oleh kode Anda yang tidak memiliki %20urutan pelarian yang sering digunakan .
Overv

@Overv Saya baru saja Direvisi
Pandya

Juga, Anda mungkin ingin memeriksa apa yang s/%26/&/gterjadi. (Saya memperbaikinya.)
G-Man

9

Perl satu liner:

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

Contoh:

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

1
Jawaban ini menarik ketika Anda tidak ingin berurusan dengan memasang modul perl.
Sridhar Sarnobat

1
Hanya satu yang bekerja secara elegan untuk saya di MacOS.
Qix


7

Saya tidak dapat mengomentari jawaban terbaik di utas ini , jadi inilah milik saya.

Secara pribadi, saya menggunakan alias ini untuk penyandian dan penguraian 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])"'

Kedua perintah memungkinkan Anda untuk mengkonversi data, diteruskan sebagai argumen baris perintah atau membacanya dari input standar , karena keduanya satu-baris memeriksa apakah ada argumen baris perintah (bahkan yang kosong) dan memprosesnya atau hanya membaca input standar jika tidak.


perbarui 2017-05-23 (penyandian slash)

Menanggapi komentar @ Bevor.

Jika Anda juga perlu menyandikan slash, cukup tambahkan argumen kosong kedua ke fungsi kutipan, maka slash juga akan disandikan.

Jadi, akhirnya urlencode alias dalam bash terlihat seperti ini:

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

Contoh

$ 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
Tidak menyandikan garis miring.
Bevor

@ Bow: Contoh?
DIG mbl

Tambahkan slash ke urlencode "Проба пера" -> hasil: Slash tidak disandikan.
Bevor

1
@ Bow: Anda benar. Terima kasih atas komentarmu. Saya juga akan mengubah jawaban saya untuk mencerminkan komentar Anda di dalamnya.
DIG mbl

4

Dan pendekatan Perl lainnya:

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

    print $uri->decode($_)
}

Anda perlu menginstal URI::Encodemodul. Di Debian saya, saya bisa berlari

sudo apt-get install liburi-encode-perl

Kemudian, saya menjalankan skrip di atas pada file uji yang berisi:

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

Hasilnya adalah (saya telah menyimpan skrip sebagai foo.pl):

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

3

Sebuah jawaban dalam shell (kebanyakan Posix):

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

Penjelasan:

  • -e 's/+/ /gmentransformasikan masing-masing +dalam ruang (seperti yang dijelaskan dalam norma url-encode)
  • -e 's/%\(..\)/\\\\x\1/g'mengubah setiap %XXdi \\xXX. Pemberitahuan salah satu \akan dihapus dengan mengutip aturan.
  • Printf bagian dalam hanya ada untuk mengirimkan input ke sed. Kami dapat menggantinya dengan mekanisme lain apa pun
  • Printf luar menafsirkan \\xXXurutan dan hasil tampilan.

Sunting:

Karena %harus selalu ditafsirkan dalam URL, dimungkinkan untuk menyederhanakan jawaban ini. Selain itu, saya pikir lebih bersih untuk menggunakan xargsdaripada backquotes (terima kasih kepada @josch).

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

Sayangnya, (seperti yang diperhatikan @josch) tidak ada solusi ini yang sesuai dengan Posix karena \xurutan escape tidak didefinisikan dalam Posix.


Selamat datang di U&L. Mungkin Anda bisa menjelaskan jawaban ini dan cara kerjanya. Kami biasanya memilih jawaban kami dalam bentuk panjang dengan detail, bukan hanya cuplikan kode.
slm

Saya sangat suka jawaban ini karena komprehensif, portabel dan tidak memerlukan program eksternal yang lebih berat seperti perl atau python. Bekerja dengan baik untuk saya.
Steve Wills

1
Solusi bagus Dan bahkan lebih pendek dan lebih cerdas: ... | sed 's/+/ /g;s/%\(..\)/\\\\x\1/g'. The -epilihan dapat dihilangkan di sini sebenarnya ...
SyntaxError

1
@ josch Anda benar, printfadalah built-in dashdan tidak mengenali \xpelarian. Anda dapat menggunakannya /usr/bin/printfsebagai gantinya printfuntuk membuatnya berfungsi. Biasanya, Anda harus dapat menggunakan command printf, tetapi tampaknya tidak berfungsi sebagaimana mestinya. Itu terus menggunakan built-in.
Jérôme Pouiller

1
@Jezz memang dukungan untuk \xmelarikan diri bukan bagian dari POSIX: pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html Selama pengujian saya, saya melihat masalah lain. Anda mungkin ingin mengganti ..regex dengan [a-zA-Z0-9][a-zA-Z0-9]karena jika tidak, input seperti '%%%' akan gagal. Saya juga menambahkan s/%/%%/gdi akhir untuk memastikan lolos dari persentase untuk printf.
josch

1

Khusus shell:

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

Tambah --atau %buntuk mencegah argumen yang dimulai dengan tanda hubung diperlakukan sebagai opsi.

In zsh ${x//%/a}menambah aakhir tetapi ${x//\%/a}menggantikan %dengan a.


1

Berikut ini adalah bit yang relevan dari skrip lain (yang tanpa malu-malu saya mencuri dari skrip unduhan youtube.com dari jawaban lain) yang pernah saya tulis sebelumnya. Ia menggunakan seddan shell untuk membangun urldecode yang berfungsi.

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

Saya tidak akan bersumpah ini komprehensif - dan sebenarnya saya ragu - tapi itu menangani youtube cukup jelas.


1

Berikut adalah fungsi BASH untuk melakukan hal itu:

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

bekerja seperti pesona
AbdElraouf Sabri

0

Solusi lain menggunakan ruby ​​(jawaban python yang diterima tidak bekerja untuk saya)

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

Contoh

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

$ urlencode 'q werty=/;'
q+werty%3D%2F%3B
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.