Bagaimana saya bisa menyandikan dan mendekodekan string yang dikodekan persen pada baris perintah?

31

Bagaimana saya bisa menyandikan dan mendekodekan string persen-disandikan (URL disandikan) pada baris perintah?

Saya mencari solusi yang dapat melakukan ini:

$ percent-encode "ændrük"
%C3%A6ndr%C3%BCk
$ percent-decode "%C3%A6ndr%C3%BCk"
ændrük
ændrük
sumber
Apakah Anda ingin memasukkan pengkodean yang berbeda juga? %E6ndr%FCktidak terlihat seperti (standar) UTF8 bagi saya. Atau hanya sebuah contoh?
mengatur
@ mengatur Terima kasih telah menangkap itu. Rupanya saya memilih apel buruk di antara hasil pencarian untuk konverter online.
ændrük
Untuk nama file, lihat: Cara menghapus pengkodean URI dalam nama file .
kenorb

Jawaban:

35

Perintah-perintah ini melakukan apa yang Anda inginkan:

python -c "import urllib, sys; print urllib.quote(sys.argv[1])" æ
python -c "import urllib, sys; print urllib.unquote(sys.argv[1])" %C3%A6

Jika Anda ingin menyandikan spasi sebagai +, ganti urllib.quotedengan urllib.quote_plus.

Saya kira Anda akan ingin alias mereka ;-)

Stefano Palazzo
sumber
1
Apa itu karakter æ di akhir baris pertama? Sunting: menjawab sendiri - mengerti, itu hanya string karakter UTF8 to-be-encoded tunggal misalnya tujuan :-)
TMG
1
bagaimana dengan python3?
RicardoE
@ RicardoE memeriksa jawaban ini .
Pablo A
27

kulit

Coba baris perintah berikut:

$ echo "%C3%A6ndr%C3%BCk" | sed 's@+@ @g;s@%@\\x@g' | xargs -0 printf "%b"
ændrük

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 yang berikut ini urlencode()dan urldecode()fungsinya:

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 kode ur Anda () menganggap data tidak mengandung garis miring terbalik.


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 .


Python

Cobalah untuk menentukan alias berikut:

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

Pemakaian:

$ urlencode "ændrük"
C%26ndrC%3Ck
$ urldecode "%C3%A6ndr%C3%BCk"
ændrük

Sumber: ruslanspivak


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

sed

Penggunaan seddapat dicapai dengan:

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

awk

Coba solusi anon :

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

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:

kenorb
sumber
Versi bash + xxd tidak berfungsi dengan string yang berisi %, mungkin Anda bisa menggantinya printf "$c"dengan printf "%c" "$c"? Masalah lain adalah bahwa beberapa karakter non-ASCII tidak dikodekan (seperti ä) dalam beberapa pengaturan bahasa, mungkin menambahkan export LC_ALL=Cfungsi a (yang seharusnya tidak mempengaruhi apa pun di luar fungsi)?
12431234123412341234123
8

Persen-encode karakter URI dan non-ASCII karakter khusus

jq -s -R -r @uri

-s( --slurp) membaca baris input ke dalam array dan -s -R( --slurp --raw-input) membaca input ke dalam satu string. -r( --raw-output) menampilkan isi string bukannya string literal JSON.

Persen-enkode semua karakter

xxd -p|tr -d \\n|sed 's/../%&/g'

tr -d \\nmenghapus umpan baris yang ditambahkan xxd -psetelah setiap 60 karakter.

Persen-sandi semua karakter kecuali karakter alfanumerik ASCII di Bash

eu () {
    local LC_ALL=C c
    while IFS= read -r -n1 -d '' c
    do 
        if [[ $c = [[:alnum:]] ]]
        then 
            printf %s "$c"
        else
            printf %%%02x "'$c"
        fi
    done
}

Tanpa -d ''ini akan melewatkan baris baris dan byte nol. Tanpa IFS=ini akan menggantikan karakter IFSdengan %00. Tanpa LC_ALL=Cini misalnya akan diganti dengan %3042di lokal UTF-8.

nisetama
sumber
5

Solusi bash murni hanya untuk decoding :

$ a='%C3%A6ndr%C3%BCk'
$ echo -e "${a//%/\\x}"
ændrük
sebentar
sumber
4

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 2015-07-16 (kosongkan 1 arg)

... menurut komentar @muru.

perbarui 2017-05-28 (penyandian slash)

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

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
DIG mbl
sumber
1
Saya pikir sys.argv[1] if len(sys.argv) > 1 else sys.stdin.read()[0:-1]mungkin lebih tepat. Terutama jika Anda menggunakan ini dalam skrip dan tanpa sengaja memberikan argumen kosong pertama.
muru
Sesuai komentar @uru saya mengubah pemeriksaan untuk argumen pada baris perintah. Itu adalah: len(sys.argv) < 2 and sys.stdin.read()[0:-1] or sys.argv[1] Sekarang: sys.argv[1] if len(sys.argv) > 1 else sys.stdin.read()[0:-1] Yaitu, jika bahkan ada argumen pertama yang kosong, perintah tidak menunggu input dari input standar, tetapi memproses argumen kosong.
DIG mbl
2

Saya menemukan sebuah paket,, renameutilsyang berisi utilitas deurlnameyang dapat mengubah nama file yang berisi karakter "persen-disandikan".

Sayangnya, ini tidak men-decode stdin atau opsi baris perintah, tetapi hanya mengganti nama file, jadi Anda harus membuat file dummy untuk mendapatkan decoding (nama file yang diganti nama), tetapi dengan beberapa bash scripting prosesnya dapat otomatis .

Tidak ada informasi tentang bagian penyandian, bahkan karena bisa dipertanyakan karakter mana yang disandikan. Hanya non-ASCII?

Saya pikir harus ada beberapa alat / metode yang lebih baik.

enzotib
sumber
1

Mirip dengan Stefano ansqer tetapi dengan Python 3:

python -c "import urllib.parse, sys; print(urllib.parse.quote(sys.argv[1]))" æ
python -c "import urllib.parse, sys; print(urllib.parse.unquote(sys.argv[1]))" %C3%A6

Untuk menyandikan juga garis miring:

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

Info lebih lanjut tentang perbedaannya di sini .

Pablo A
sumber
0

Berikut adalah fungsi POSIX Awk untuk penyandian:

function encodeURIComponent(str, j, q) {
  while (y++ < 125) z[sprintf("%c", y)] = y
  while (y = substr(str, ++j, 1))
    q = y ~ /[[:alnum:]_.!~*\47()-]/ ? q y : q sprintf("%%%02X", z[y])
  return q
}

Contoh

Steven Penny
sumber