Saya mencoba menulis skrip bash untuk pengujian yang mengambil parameter dan mengirimkannya melalui curl ke situs web. Saya perlu url mengkodekan nilai untuk memastikan bahwa karakter khusus diproses dengan benar. Apa cara terbaik untuk melakukan ini?
Berikut ini skrip dasar saya:
#!/bin/bash
host=${1:?'bad host'}
value=$2
shift
shift
curl -v -d "param=${value}" http://${host}/somepath $@
Jawaban:
Gunakan
curl --data-urlencode
; dariman curl
:Contoh penggunaan:
Lihat halaman manual untuk info lebih lanjut.
Ini membutuhkan curl 7.18.0 atau lebih baru (dirilis Januari 2008) . Gunakan
curl -V
untuk memeriksa versi yang Anda miliki.Anda juga dapat menyandikan string kueri :
sumber
curl -G --data-urlencode "blah=df ssdf sdf" --data-urlencode "blah2=dfsdf sdfsd " http://whatever.com/whatever
curl --data-urlencode "description=![image]($url)" www.example.com
. Ada yang tahu kenapa? `"
dari‽Ini jawaban murni BASH.
Anda dapat menggunakannya dalam dua cara:
[diedit]
Inilah fungsi rawurldecode () yang cocok, yang - dengan segala kerendahan hati - mengagumkan.
Dengan set yang cocok, kami sekarang dapat melakukan beberapa tes sederhana:
Dan jika Anda benar-benar merasa bahwa Anda memerlukan alat eksternal (well, itu akan jauh lebih cepat, dan mungkin melakukan file biner dan semacamnya ...) Saya menemukan ini di router OpenWRT saya ...
Di mana url_escape.sed adalah file yang berisi aturan-aturan ini:
sumber
Jogging «à l'Hèze»
menghasilkanJogging%20%abà%20l%27Hèze%bb
yang tidak bisa diumpankan ke JSdecodeURIComponent
:(\u0144
) ia akan menampilkan% 144 secara naif, ╡ (\u2561
) akan menjadi keluaran sebagai% 2561. Jawaban rawurlencoded yang benar untuk masing-masing adalah% C5% 84% 0A dan% E2% 95% A1.Gunakan
URI::Escape
modul danuri_escape
fungsi Perl di baris kedua skrip bash Anda:Sunting: Perbaiki masalah mengutip, seperti yang disarankan oleh Chris Johnsen dalam komentar. Terima kasih!
sumber
echo
, pipa dan<>
), dan sekarang berfungsi bahkan ketika $ 2 berisi tanda kutip atau tanda kutip ganda. Terima kasih!echo
juga:value="$(perl -MURI::Escape -e 'print uri_escape($ARGV[0]);' "$2")"
Pilihan lain adalah menggunakan
jq
(sebagai filter):-R
(--raw-input
) memperlakukan jalur input sebagai string alih-alih menguraikannya sebagai JSON dan-sR
(--slurp --raw-input
) membaca input menjadi string tunggal.-r
(--raw-output
) menampilkan isi string bukannya string literal JSON.Jika input bukan output dari perintah lain, Anda dapat menyimpannya dalam
jq
variabel string:-n
(--null-input
) tidak membaca input, dan--arg name value
menyimpanvalue
dalam variabelname
sebagai string. Di filter,$name
(dalam tanda kutip tunggal, untuk menghindari ekspansi oleh shell), referensi variabelname
.Dibungkus sebagai fungsi Bash, ini menjadi:
Atau ini persen-encode semua byte:
sumber
curl
untuk menyandikan yang berfungsi dan jika bash memiliki builtin yang akan diterima - tetapijq
sepertinya pas untuk saya, saya masih jauh dari mencapai tingkat kenyamanan dengan alat ini)@uri
bukan beberapa variabel, tetapi filter jq literal yang digunakan untuk memformat string dan melarikan diri; lihat manual jq untuk detail (maaf, tidak ada tautan langsung, perlu mencari@uri
di halaman ...)printf "http://localhost:8082/" | jq -sRr '@uri'
demi kelengkapan, banyak solusi menggunakan
sed
atauawk
hanya menerjemahkan serangkaian karakter khusus dan karenanya cukup besar berdasarkan ukuran kode dan juga jangan menerjemahkan karakter khusus lain yang harus dikodekan.cara aman untuk urlencode adalah dengan hanya menyandikan setiap byte - bahkan yang sudah diizinkan.
xxd berhati-hati di sini bahwa input ditangani sebagai byte dan bukan karakter.
edit:
xxd hadir dengan paket vim-common di Debian dan saya hanya menggunakan sistem yang tidak diinstal dan saya tidak ingin menginstalnya. Altornative adalah menggunakan
hexdump
dari paket bsdmainutils di Debian. Menurut grafik berikut, bsdmainutils dan vim-common harus memiliki kemungkinan yang hampir sama untuk diinstal:http://qa.debian.org/popcon-png.php?packages=vim-common%2Cbsdmainutils&show_installed=1&want_legend=1&want_ticks=1
namun demikian di sini versi yang menggunakan
hexdump
alih-alihxxd
dan memungkinkan untuk menghindaritr
panggilan:sumber
xxd -plain
harus terjadi SETELAHtr -d '\n'
!\n
karakter akan diterjemahkan olehxxd -plain
ke0a
. Jangan mengambil kata-kata saya untuk itu, coba sendiri:echo -n -e '\n' | xxd -plain
Ini membuktikan bahwa Andatr -d '\n'
tidak berguna di sini karena tidak mungkin ada\n
setelahxxd -plain
Kedua,echo foobar
tambahkan\n
karakter sendiri di akhir string karakter, jadixxd -plain
jangan diberi makanfoobar
seperti yang diharapkan tetapi denganfoobar\n
. kemudianxxd -plain
menerjemahkannya ke beberapa string karakter yang berakhir0a
, membuatnya tidak cocok untuk pengguna. Anda bisa menambahkan-n
untukecho
mengatasinya.xxd
panggilan itu ada di depantr -d
panggilan. Itu milik di sana sehingga setiap baris baru dalamfoobar
diterjemahkan olehxxd
. Thetr -d
setelahxxd
panggilan untuk menghapus baris yang xxd menghasilkan. Tampaknya Anda tidak pernah memiliki foobar cukup lama sehinggaxxd
menghasilkan baris baru tetapi untuk input panjang itu akan. Jaditr -d
itu perlu. Berbeda dengan asumsi Anda,tr -d
BUKAN untuk menghapus baris baru dari input tetapi darixxd
output. Saya ingin menyimpan baris baru di input. Satu-satunya poin Anda yang valid adalah, gema itu menambahkan baris baru yang tidak perlu.echo -n
yang memang saya lewatkanSalah satu varian, mungkin jelek, tetapi sederhana:
Berikut ini adalah versi satu-liner misalnya (seperti yang disarankan oleh Bruno ):
sumber
date
perintah ...date | curl -Gso /dev/null -w %{url_effective} --data-urlencode @- "" | cut -c 3-
(Anda haruscut
mematikan 2 karakter pertama, karena output curl adalah secara teknis URL relatif dengan string kueri.)%0A
di akhir, gunakanprintf
sebagai gantiecho
.Saya merasa lebih mudah dibaca dengan python:
triple 'memastikan bahwa tanda kutip nilai tidak akan merugikan. urllib ada di perpustakaan standar. Ini berfungsi sebagai contoh untuk url (dunia nyata) yang gila ini:
sumber
encoded_value=$(python3 -c "import urllib.parse; print (urllib.parse.quote('''$value'''))")
.python -c 'import urllib, sys; sys.stdout.writelines(urllib.quote_plus(l, safe="/\n") for l in sys.stdin)'
hampir tidak memiliki masalah mengutip, dan harus efisien dalam memori / kecepatan (belum diperiksa, simpan untuk menyipitkan mata)sys.argv
daripada mengganti$value
ke string yang kemudian diuraikan sebagai kode. Bagaimana jikavalue
terkandung''' + __import__("os").system("rm -rf ~") + '''
?python -c "import urllib;print urllib.quote(raw_input())" <<< "$data"
Saya telah menemukan potongan berikut berguna untuk memasukkannya ke dalam rangkaian panggilan program, di mana URI :: Escape mungkin tidak diinstal:
( sumber )
sumber
perl -pe 's/\%(\w\w)/chr hex $1/ge'
(sumber: unix.stackexchange.com/questions/159253/… )perl -pe 's/(\W)/sprintf("%%%02X", ord($1))/ge'
yang memungkinkan huruf, angka, dan garis bawah, tetapi menyandikan yang lainnya.Jika Anda ingin menjalankan
GET
permintaan dan menggunakan ikal murni, tambahkan saja--get
ke solusi @ Jacob.Berikut ini sebuah contoh:
sumber
Tautan langsung ke versi awk: http://www.shelldorado.com/scripts/cmds/urlencode
Saya menggunakannya selama bertahun-tahun dan berfungsi seperti pesona
sumber
Ini mungkin yang terbaik:
sumber
after=$(echo -e ...
od
perintah tidak umum.od
karena menggunakan format output yang berbeda dari GNUod
. Misalnyaprintf aa|od -An -tx1 -v|tr \ -
mencetak-----------61--61--------------------------------------------------------
dengan OS Xod
dan-61-61
dengan GNUod
. Anda dapat menggunakannyaod -An -tx1 -v|sed 's/ */ /g;s/ *$//'|tr \ %|tr -d \\n
dengan OS Xod
atau GNUod
.xxd -p|sed 's/../%&/g'|tr -d \\n
melakukan hal yang sama, meskipunxxd
tidak dalam POSIX tetapiod
.Inilah solusi Bash yang tidak menjalankan program eksternal apa pun:
sumber
á
ini akan menyandikan string di dalam $ 1 dan menghasilkannya dalam $ url. meskipun Anda tidak harus memasukkannya ke dalam var jika Anda mau. BTW tidak termasuk sed untuk tab pikir itu akan mengubahnya menjadi spasi
sumber
Menggunakan php dari skrip shell:
sumber
Bagi Anda yang mencari solusi yang tidak membutuhkan perl, berikut ini adalah yang hanya membutuhkan hexdump dan awk:
Dijahit bersama dari beberapa tempat di internet dan beberapa percobaan dan kesalahan lokal. Ini sangat bagus!
sumber
uni2ascii sangat berguna:
sumber
%
dan spasi (yang terakhir dapat diperbaiki dengan-s
bendera)Jika Anda tidak ingin bergantung pada Perl, Anda juga dapat menggunakan sed. Agak berantakan, karena setiap karakter harus melarikan diri secara individual. Buat file dengan konten berikut dan panggil itu
urlencode.sed
Untuk menggunakannya lakukan hal berikut.
Ini akan membagi string menjadi bagian yang perlu dikodekan, dan bagian yang baik-baik saja, mengkodekan bagian yang membutuhkannya, lalu menjahit kembali menjadi satu.
Anda dapat memasukkannya ke dalam skrip sh untuk kenyamanan, mungkin memerlukannya mengambil parameter untuk menyandikan, meletakkannya di jalur Anda dan kemudian Anda bisa memanggil:
sumber
sumber
Anda dapat meniru javascript
encodeURIComponent
dalam perl. Inilah perintahnya:Anda dapat mengatur ini sebagai alias bash di
.bash_profile
:Sekarang Anda dapat mengirim pipa ke
encodeURIComponent
:sumber
Inilah versi simpulnya:
sumber
node
semuanya. Saya memposting solusi Bash-only. :)node -p 'encodeURIComponent(require("fs").readFileSync(0))'
Pertanyaannya adalah tentang melakukan ini di bash dan tidak perlu untuk python atau perl karena sebenarnya ada satu perintah yang melakukan apa yang Anda inginkan - "urlencode".
Ini juga jauh lebih baik, karena jawaban perl di atas, misalnya, tidak menyandikan semua karakter dengan benar. Cobalah dengan tanda hubung panjang yang Anda dapatkan dari Word dan Anda mendapatkan kode yang salah.
Catatan, Anda perlu "gridsite-clients" diinstal untuk memberikan perintah ini.
sumber
urlencode
. Versi apa yang Anda gunakan?Opsi PHP sederhana:
sumber
Ruby, untuk kelengkapan
sumber
Pendekatan php lain:
sumber
echo
akan menambahkan karakter baris baru (hex0xa
). Untuk berhenti melakukannya, gunakanecho -n
.Ini adalah versi saya untuk shell ash busybox untuk sistem tertanam, saya awalnya mengadopsi varian Orwellophile:
sumber
Berikut adalah fungsi POSIX untuk melakukan itu:
Contoh:
Sumber
sumber
Berikut ini adalah konversi satu baris menggunakan Lua, mirip dengan jawaban blueyed kecuali dengan semua RFC 3986 Karakter yang Tidak Ditangguhkan dibiarkan tidak tersandi (seperti jawaban ini ):
Selain itu, Anda mungkin perlu memastikan bahwa baris baru di string Anda dikonversi dari LF ke CRLF, dalam hal ini Anda bisa memasukkan a
gsub("\r?\n", "\r\n")
dalam rantai sebelum pengkodean persen.Inilah varian yang, dalam gaya aplikasi / x-www-form-urlencoded yang tidak standar, apakah itu normalisasi baris baru, serta ruang enkode sebagai '+' alih-alih '% 20' (yang mungkin dapat ditambahkan ke Cuplikan Perl menggunakan teknik serupa).
sumber
Setelah menginstal php saya menggunakan cara ini:
sumber
Ini adalah versi ksh dari jawaban orwellophile yang berisi fungsi rawurlencode dan rawurldecode (tautan: Bagaimana cara urlencode data untuk perintah curl? ). Saya tidak punya cukup perwakilan untuk memposting komentar, karenanya posting baru ..
sumber
Apa yang akan mem-parsing URL lebih baik daripada javascript?
sumber
node -p 'encodeURIComponent(require("fs").readFileSync(0))'
echo | ...
salah, sementaraecho -n | ...
menekan baris baru.Berikut ini didasarkan pada jawaban Orwellophile, tetapi memecahkan bug multibyte yang disebutkan dalam komentar dengan mengatur LC_ALL = C (trik dari vte.sh). Saya telah menulisnya dalam bentuk fungsi yang sesuai PROMPT_COMMAND, karena itulah cara saya menggunakannya.
sumber